按相乘排序


34

您应该编写一个程序或函数,给定正整数列表,将每个元素与可能的最小正整数相乘,以创建严格增加的列表。

例如,如果输入是

5 4 12 1 3

乘法将是

5*1=5 4*2=8 12*1=12 1*13=13 3*5=15

输出将是递增列表

5 8 12 13 15

输入项

  • 包含至少1个元素的正整数列表

输出量

  • 正整数列表

例子

9 => 9
1 2 => 1 2
2 1 => 2 3
7 3 => 7 9
1 1 1 1 => 1 2 3 4
5 4 12 1 3 => 5 8 12 13 15
3 3 3 8 16 => 3 6 9 16 32
6 5 4 3 2 1 => 6 10 12 15 16 17
9 4 6 6 5 78 12 88 => 9 12 18 24 25 78 84 88
8 9 41 5 12 3 5 6 => 8 9 41 45 48 51 55 60
15 8 12 47 22 15 4 66 72 15 3 4 => 15 16 24 47 66 75 76 132 144 150 153 156

这是代码高尔夫球,因此最短的程序或功能将获胜。

有趣的事实:输入的输出的最后一个元素N, N-1, ... ,1似乎是(N+1)th序列A007952的元素。如果找到证明,欢迎您将其包括在高尔夫答案中或将其发布为评论。


有人在那项证据上取得了进展吗?
康纳·克拉克

Answers:


20

果冻6 5 字节

:‘×µ\

在@Dennis醒来殴打我之前, 第一个果冻回答在线尝试!

说明

:          Integer division, m//n
 ‘         Increment, (m//n+1)
  ×        Multiply, (m//n+1)*n
   µ       Turn the previous links into a new monadic chain
    \      Accumulate on the array

感谢@Dennis提供-1个字节。


4
:‘×µ\保存一个字节。
丹尼斯

20
@丹尼斯哦,他醒了
丹尼斯·范·

9

JavaScript(ES6),28

编辑如@Patrick Roberts所建议,p可以是未初始化的参数。字节数相同,但避免使用全局变量

(a,p)=>a.map(n=>p=n*-~(p/n))

测试

f=(a,p)=>a.map(n=>p=n*-~(p/n))

console.log=x=>O.textContent+=x+'\n'

;[
[[9], [ 9]],
[[1, 2], [ 1, 2]],
[[2, 1], [ 2, 3]],
[[7, 3], [ 7, 9]],
[[1, 1, 1, 1], [ 1, 2, 3, 4]],
[[5, 4, 12, 1, 3], [ 5, 8, 12, 13, 15]],
[[3, 3, 3, 8, 16], [ 3, 6, 9, 16, 32]],
[[6, 5, 4, 3, 2, 1], [ 6, 10, 12, 15, 16, 17]],
[[9, 4, 6, 6, 5, 78, 12, 88], [ 9, 12, 18, 24, 25, 78, 84, 88]],
[[8, 9, 41, 5, 12, 3, 5, 6], [ 8, 9, 41, 45, 48, 51, 55, 60]],
[[15, 8, 12, 47, 22, 15, 4, 66, 72, 15, 3, 4], [ 15, 16, 24, 47, 66, 75, 76, 132, 144, 150, 153, 156]]
].forEach(t=>{
  var i=t[0],k=t[1],r=f(i),ok=(k+'')==(r+'')
  console.log(i + ' => ' + r + (ok?' OK':'FAIL expecting '+x))
})
<pre id=O></pre>


我认为您可以使用模来节省一些字节,就像我在答案中所做的那样。
2016年

您不能跳过p = 0吗?您需要它才能在多个列表上同时运行它,但问题仅是单个列表
Charlie Wynn

1
@CharlieWynn如果不初始化变量,则会得到未定义变量的错误。如果偶然该变量已经存在(很容易在网页环境中发生),则它可能有任何错误的值。
edc65 '16

@ edc65肯定,p已在此页面上定义!
查理·永利

1
@PatrickRoberts再三考虑,我仍然可以避免使用globals :f=a=>a.map(n=>a+=n-a%n,a=0)。但这不是我的算法(对不起我),所以我将保持原样并
赞成aross

6

Python 2,67 64字节

首先尝试进行代码组合,因此建议您多加注意。

def m(l):
 for x in range(1,len(l)):l[x]*=l[x-1]/l[x]+1
 print l

嗨,我想您正在将行返回计数为2个字节(使用Windows吗?),但是在此站点上,您会将行返回计数为单个字节。因此,您的分数实际上是65个字节。(如果不确定,您可以将代码复制并粘贴到mothereff.in/byte-counter中。)此外,您可以这样做,print l而不是return l保存另一个字节。不错的工作!
mathmandan '16

谢谢,我不知道退货。这就解释了为什么我总是得到不同的字节数。而且我什至没有考虑过,打印就足够了,也不必返回列表。
Taronyu

没问题!顺便说一句,由于您提到了“技巧”,因此您可能有兴趣浏览codegolf.stackexchange.com/questions/54/…。请享用!
mathmandan '16

5

PHP,55 46 42 41字节

使用ISO 8859-1编码。

for(;$a=$argv[++$i];)echo$l+=$a-$l%$a,~ß;

像这样运行(-d仅出于美观目的而添加):

php -d error_reporting=30709 -r 'for(;$a=$argv[++$i];)echo$l+=$a-$l%$a,~ß;' 10 10 8
  • 已将1个字节的字节保存到Ismael Miguel。
  • 使用取模而不是地板节省了8个字节
  • 将4字节的thx保存到Ismael Miguel(用于代替foreach)
  • 使用产生一个空格保存一个字节。

我认为您可以将替换$a+0+$a。另外,您可以假设输入将永远不会有0,因此,您可以将其替换$a+0&&print为simple +$a&print。实际上,$a&print从PHP开始,您甚至可以做到"0" == 0 == 0.0 == false。但echo我认为,如果仅使用,则可能不需要。
伊斯梅尔·米格尔

二进制and将不起作用(与逻辑相反),也不会以这种方式回显。由于我要从CLI获取输入,因此第一个参数是-,我想捕获而不是打印零。尝试php -r 'print_r($argv);' foo。不过,您的第一个建议还是节省了1个字节。
2016年

1
怎么for(;$a=$argv[++$i];)echo$l+=$a-$l%$a,' ';样 它是42个字节长,并跳过第一个元素。
Ismael Miguel

尼斯之一,THX @IsmaelMiguel
aross

别客气。如果您想真正变态,可以将替换为a^A,但这会溢出太多警告(警告是可忽略的)。它不会以任何方式更改字节数,但肯定会有所不同。
Ismael Miguel

4

哈斯克尔(30 28 25个字节)

scanl1(\x y->y*div x y+y)

扩展版

f :: Integral n => [n] -> [n]
f xs = scanl1 increaseOnDemand xs
 where
   increaseOnDemand :: Integral n => n -> n -> n
   increaseOnDemand acc next = next * (1 + acc `div` next)

说明

scanl1使您可以折叠列表并将所有中间值累加到另一个列表中。这是的特化形式scanl,具有以下类型:

scanl  :: (acc  -> elem -> acc)  -> acc -> [elem] -> [acc]
scanl1 :: (elem -> elem -> elem) ->        [elem] -> [elem]

scanl1 f (x:xs) = scanl f x xs

因此,我们需要的是一个合适的函数,该函数接受列表的最后两个元素(acc在扩展版本中)和我们要处理的元素(next在扩展版本中)并返回合适的数字。

我们可以通过将累加器除以下一个并将结果取底来轻松得出该数字。div照顾那个。之后,我们只需添加1以确保列表实际上在增加(并且我们不会以结尾0)。


无需为函数命名。您也可以将替换为( ... )$ ...我认为您已经算出了最后一个换行符,可以省略:scanl1$\x y->y*div x y+y24个字节。
nimi 2016年

@nimi:真的吗?表情数吗?话虽这么说,我没有用(...)vs 保留任何字节$,因为它$\ 被解析为运算符,并且之后需要一个空格$
Zeta,2016年

默认情况下允许scanl1(...)使用未命名的函数,这是未命名的函数。关于$vs ():您是对的,我的错。
nimi 2016年

4

C ++, 63 60 57个字节

void s(int*f,int*e){for(int c=*f;++f!=e;c=*f+=c/ *f**f);}

给定范围就位工作[first, last)。最初是作为模板变体编写的,但是更长:

template<class T>void s(T f,T e){for(auto c=*f;++f!=e;c=*f+=c/ *f**f);}

扩大的视野

template <class ForwardIterator>
void sort(ForwardIterator first, ForwardIterator last){
    auto previous = *first;

    for(++first; first != last; ++first){
        auto & current = *first;
        current += current * (current / previous);
        previous = current;
    }
}

3

CJam,13个字节

q~{\_p1$/)*}*

输入为CJam样式列表。输出以换行分隔。

在这里测试。

说明

q~    e# Read and evaluate input.
{     e# Fold this block over the list (i.e. "foreach except first")...
  \   e#   Swap with previous value.
  _p  e#   Duplicate and print previous value.
  1$  e#   Copy current value.
  /   e#   Integer division.
  )*  e#   Increment and multiply current value by the result.
}*

最终值保留在堆栈中,并在最后自动打印。


3

Mathematica, 36 32字节

 #2(Floor[#1/#2]+1)&~FoldList~#&

测试

#2(Floor[#1/#2]+1)&~FoldList~#& /@ {{5, 4, 12, 1, 3}, 
   {15, 8, 12, 47, 22, 15, 4, 66, 72, 15, 3, 4}}
(* {{5, 8, 12, 13, 15}, {15, 16, 24, 47, 66, 75, 76, 132, 144, 
  150, 153, 156}} *)

3

Perl,17 + 3 = 20字节

$p=$_*=$==1+$p/$_

要求-p-l标志:

$ perl -ple'$p=$_*=$==1+$p/$_' <<< $'15\n8\n12\n47\n22\n15\n4\n66\n72\n15\n3\n4'
15
16
24
47
66
75
76
132
144
150
153
156

说明:

# '-p' reads each line into $_ and auto print
# '-l' chomp off newline on input and also inserts a new line when printing
# When assigning a number to `$=` it will automatic be truncated to an integer
# * Added newlines for each assignment 
$p=
  $_*=
    $==
      1+$p/$_

3

Python(3.5),63 62字节

def f(a):
 r=[0]
 for i in a:r+=i*(r[-1]//i+1),
 return r[1:]

测试

>>> print('\n'.join([str(i)+' => '+str(f(i)) for i in [[9],[1,2],[2,1],[7,3],[1,1,1,1],[5,4,12,1,3],[3,3,3,8,16],[6,5,4,3,2,1],[9,4,6,6,5,78,12,88],[8,9,41,5,12,3,5,6],[15,8,12,47,22,15,4,66,72,15,3,4]]]))
[9] => [9]
[1, 2] => [1, 2]
[2, 1] => [2, 3]
[7, 3] => [7, 9]
[1, 1, 1, 1] => [1, 2, 3, 4]
[5, 4, 12, 1, 3] => [5, 8, 12, 13, 15]
[3, 3, 3, 8, 16] => [3, 6, 9, 16, 32]
[6, 5, 4, 3, 2, 1] => [6, 10, 12, 15, 16, 17]
[9, 4, 6, 6, 5, 78, 12, 88] => [9, 12, 18, 24, 25, 78, 84, 88]
[8, 9, 41, 5, 12, 3, 5, 6] => [8, 9, 41, 45, 48, 51, 55, 60]
[15, 8, 12, 47, 22, 15, 4, 66, 72, 15, 3, 4] => [15, 16, 24, 47, 66, 75, 76, 132, 144, 150, 153, 156]

先前的解决方案

一些递归解决方案,但更大

(68 bytes) f=lambda a,i=0:[i,*f(a[1:],a[0]*(i//a[0]+1))][i==0:]if a!=[]else[i]
(64 bytes) f=lambda a,i=0:a>[]and[i,*f(a[1:],a[0]*(i//a[0]+1))][i<1:]or[i]

另外r+=[…],您可以使用r+=…,
Cyoce '16

@Cyoce我做出改变,但是当我定义的r=[0]默认参数r成为外地
二万

没错,我忘记了Python如何处理默认参数。其他尖端应的工作,虽然
Cyoce

@Cyoce是它的工作原理感谢秘诀
二万

3

Brachylog,12个字节

{≤.;?%0∧}ᵐ<₁

尝试将每个变量乘以数字足够奇怪,这始于尝试乘以2而不是0或1。但这似乎可行,并且击败了其他两个Brachylog实现

说明

{       }ᵐ          --  Map each number
 ≤.                 --      to a number greater or equal to the original
  .;?%0             --      and a multiple of the original
       ∧            --      no more constraints
          <₁        --  so that the list is strictly increasing

在线尝试!


2

Brachylog,54个字节

:_{h_.|[L:T],LhH,(T_,IH;0:$Ie*H=:T>I),Lb:I:1&:[I]rc.}.

说明

:_{...}.                § Call sub-predicate 1 with [Input, []] as input. Unify its output
                        § with the output of the main predicate


§ Sub-predicate 1

h_.                     § If the first element of the input is an empty list, unify the
                        § output with the empty list
|                       § Else
[L:T],LhH,              § Input = [L,T], first element of L is H
    (T_,IH              §     If T is the empty list, I = H
    ;                   §     Else
    0:$Ie*H=:T>I),      §     Enumerate integers between 0 and +inf, stop and unify the
                        §     enumerated integer with I only if I*H > T
Lb:I:1&                 § Call sub-predicate 1 with input [L minus its first element, I]
:[I]rc.                 § Unify the output of the sub-predicate with
                        § [I|Output of the recursive call]

2

珀斯,11岁

t.u*Yh/NYQ0

测试套件

进行累积归约,以归结开始的所有中间值的归约0。由于保证输入仅包含正整数,因此可以。在每一步中,我们将旧值除以新值1,然后加上,然后乘以新值。


2

C,79字节

p;main(x,v)char**v;{for(;*++v;printf("%d ",p=((x+p-1)/x+!(p%x))*x))x=atoi(*v);}

不打高尔夫球

p; /* previous value */

main(x,v) char**v;
{
    /* While arguments, print out x such that x[i] > x[i-1] */
    for(;*++v; printf("%d ", p = ((x+p-1)/x + !(p%x)) * x))
        x = atoi(*v);
}

不行p=p/x*x+x
尼尔

@Neil是的,那行得通。绝对超人了:)
科尔·卡梅隆

2

PowerShell,26个字节

$args[0]|%{($l+=$_-$l%$_)}

将输入作为显式数组,例如, > .\sort-by-multiplying.ps1 @(6,5,4,3,2,1) via $args[0]

然后,我们使用进行循环|%{...},每次迭代执行魔术。不,开个玩笑,我们使用与其他答案相同的模数技巧(@aross的道具,因为我首先在这里发现了它)。

封装体 (...)确保将数学运算的结果放置在管道上并因此输出。如果我们将其保留,则不会执行任何输出,因为$l在执行完成后将对变量进行垃圾回收。

PS C:\Tools\Scripts\golfing> .\sort-by-multiplying.ps1 @(8,9,1,5,4)
8
9
10
15
16

1

Japt,11个字节

Uå@Y*-~(X/Y

在线测试!

怎么运行的

          // Implicit: U = input array of integers
Uå@       // Cumulative reduce: map each previous value X and current value Y to:
-~(X/Y    //  floor(X/Y+1).
          // Implicit: output last expression

1

05AB1E,11个字节

码:

R`[=sŽDŠ/ò*

在线尝试!

说明:

R            # Reverse input
 `           # Flatten the list
  [          # While loop
   =         # Print the last item
    s        # Swap the last two items
     Ž       # If the stack is empty, break
      D      # Duplicate top of the stack
       Š     # Pop a,b,c and push c,a,b
        /    # Divide a / b
         ò   # Inclusive round up
          *  # Multiply the last two items

使用CP-1252编码。


1

Minkolang 0.15,17个字节

nd1+?.z0c:1+*d$zN

在这里尝试!

说明

nd                   Take number from input and duplicate it
  1+                 Add 1
    ?.               Stop if top of stack is 0 (i.e., when n => -1 because input is empty).
      z              Push value from register
       0c            Copy first item on stack
         :           Pop b,a and push a//b
          1+         Add 1
            *        Multiply
             d$z     Duplicate and store in register
                N    Output as number

从本质上讲,寄存器保留升序列表的最新成员,然后将其除以输入,然后递增以获得下一个成员的乘数。Minkolang的代码字段具有环形功能,这意味着它可以水平循环,而无需()or []循环。


1

Brachylog,21个字节

l~lCℕ₁ᵐ≤ᵛ~+?&;Cz≜×ᵐ<₁

在线尝试!

使用输入值的总和作为上限系数C。非常慢,如果输入列表长度超过5或6(也取决于值的总和),则在TIO上超时。但不如我的原始版本慢,它需要多达3个元素的微小列表以及微小的值,以免超时:

21字节

l~l.&+^₂⟦₁⊇.;?z/ᵐℕ₁ᵐ∧

在线尝试!



1

Python 2,53个字节

lambda a:reduce(lambda b,v:b+[b[-1]/v*v+v],a,[0])[1:]

在线尝试!

k*x>y暗示k>y/x; 所以最小k可以是k=floor(y/x)+1。由于在Python 2.7中,整数除法已经被当作floor,我们想要k=y/x+1k*x = (y/x+1)*x = y/x*x+x


0

Oracle SQL 11.2,210字节

WITH v AS(SELECT TO_NUMBER(COLUMN_VALUE)a,rownum i FROM XMLTABLE(('"'||REPLACE(:1,' ','","')||'"'))),c(p,n)AS(SELECT a,2 FROM v WHERE i=1UNION ALL SELECT a*CEIL((p+.1)/a),n+1 FROM c,v WHERE i=n)SELECT p FROM c;

未打高尔夫球

WITH v AS                                           
(
  SELECT TO_NUMBER(COLUMN_VALUE)a, rownum i            -- Convert the input string into rows 
  FROM   XMLTABLE(('"'||REPLACE(:1,' ','","')||'"'))   -- using space as the separator between elements
)
, c(p,n) AS                        
(
  SELECT a, 2 FROM v WHERE i=1                         -- Initialize the recursive view
  UNION ALL 
  SELECT a*CEIL((p+.1)/a),n+1 FROM c,v WHERE i=n       -- Compute the value for the nth element
)
SELECT p FROM c;

0

Chez方案(140字节)

高尔夫球版:

(define(f l)(define(g l p m)(cond((null? l)l)((<(*(car l)m)(+ p 1))(g l p(+ m 1)))(else(cons(*(car l)m)(g(cdr l)(* m(car l))1)))))(g l 0 1))

非高尔夫版本:

(define(f l)
  (define(g l p m)
    (cond
      ((null? l) l)
      ((< (* (car l) m) (+ p 1)) (g l p (+ m 1)))
      (else (cons (* (car l) m) (g (cdr l) (* m (car l)) 1)))
    )
  )
  (g l 0 1)
)

在线尝试!


* m(car l)可以*(car l)m
乔纳森·弗雷希

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.