Сортувати за множенням


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 . Якщо ви знайдете доказ, вас запрошують включити у відповідь про гольф або опублікувати як коментар.


хтось ще зробив грунт на цьому доказі?
Коннор Кларк

Відповіді:


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
@Dennis О, лайно, він прокинувся
Денніс ван Гілс

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>


Я думаю, ви можете зберегти кілька байтів за допомогою модуля, як я зробив у своїй відповіді .
1616

Ви не можете пропустити p = 0? Вам потрібно, щоб запустити його кілька разів у кількох списках, але питання стосується лише одного списку
Charlie Wynn

1
@CharlieWynn, якщо ви не ініціалізуєте змінну, ви отримаєте помилку для невизначеної змінної. Якщо випадково змінна вже існує (що легко може трапитися в середовищі веб-сторінки), вона може мати неправильне значення.
edc65

@ edc65 впевнено, p вже визначено на цій сторінці!
Charlie Wynn

1
@PatrickRoberts мислення знову, я все ще міг уникнути глобальний: f=a=>a.map(n=>a+=n-a%n,a=0). Але це не мій алгоритм (нерозумно мені), тому я буду тримати свою так, як є, і надсилати попереду
edc65

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

Дякую, я не знав про повернення рядків. Це пояснює, чому я завжди маю різні підрахунки байтів. І я навіть не вважав, що друк достатній, і список не повинен повертати.
Тароню

Без проблем! BTW, оскільки ви згадали, що "поради оцінені", вам може бути цікаво переглядати сторінку codegolf.stackexchange.com/questions/54/… . Насолоджуйтесь!
mathmandan

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 байт THX для Ісмаїла Мігеля.
  • Збережено 8 байт, використовуючи модуль замість підлоги
  • Збережено 4 байти thx для Ісмаїла Мігеля (для замість того, щоб передбачити)
  • Збережено байт за допомогою пробілу.

Я думаю , що ви можете замінити $a+0з +$a. Крім того, ви можете припустити, що вхід ніколи не матиме 0, так що ви можете замінити свій $a+0&&printна просто +$a&print. Насправді ви навіть могли це зробити $a&print, оскільки в PHP "0" == 0 == 0.0 == false. Але це може не знадобитися, якщо ви просто використовуєте echo, я думаю.
Ісмаїл Мігель

Бінарне andне буде працювати (на відміну від логічного), і не буде повторюватися таким чином. Оскільки я беру дані від CLI, першим аргументом є те -, що я хочу зловити замість того, щоб надрукувати нуль. Спробуйте php -r 'print_r($argv);' foo. Збережено 1 байт з першою пропозицією, THX.
1616

1
Як щодо for(;$a=$argv[++$i];)echo$l+=$a-$l%$a,' ';? Вона становить 42 байти і пропускає перший елемент.
Ісмаїл Мігель

Хороший, thx @IsmaelMiguel
1616

Ласкаво просимо. Якщо ви хочете бути справді чудернацькими, ви можете замінити простір на a^A, але це призведе до занадто багато попереджень (попередження невідомі). Це ніяк не змінить номер рахунку, але напевно виглядає інакше.
Ісмаїл Мігель

4

Haskell (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: Дійсно? Вирази рахуються? При цьому, я не економлю жодних байтів у (...)порівнянні з vs $, оскільки $\ він розбирається як оператор, і мені знадобиться єдиний пробіл після $.
Зета

неназвана функція дозволена за замовчуванням a scanl1(...)- це неназвана функція. Щодо $проти (): ти маєш рацію, моя помилка.
німі

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

Математика, 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

Пітон (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

@Cyoce я вношу зміни, але коли я визначаю r=[0]параметр за замовчуванням, rстають нелокальними
Ерван

Ви праві, я забув, як Python обробляв параметри за замовчуванням. Інша порада, однак, має спрацювати
Cyoce

@Cyoce так, це працює спасибі за поради
Ерван

3

Брахілог , 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

Брахілог , 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)через $args[0].

Потім ми перев'язуємо це за допомогою |%{...}кожної ітерації і виконуємо магію . Ні, просто жартую, ми використовуємо один і той же по модулю трюк інших відповідей (реквізит до @aross , тому що я вгледів там першим).

Інкапсулюючі парени (...)забезпечують, щоб результат математичної операції був розміщений на трубопроводі і таким чином виводився. Якщо ми залишили їх вимкненими, нічого не вийде, оскільки $lзмінна збирається сміттям після завершення виконання.

Приклад

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


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

Мінколанг 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 код з полем , що петлі по горизонталі без необхідності ()або []петель.


1

Брахілог , 21 байт

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

Спробуйте в Інтернеті!

В якості верхньої межі використовується сума вхідних значень для коефіцієнтів C. Досить повільно, таймаут TIO для довжин списку вхідних даних понад 5 або 6 (також залежно від суми значень). Але не так повільно, як у моїй оригінальній версії, яка вимагає крихітних списків до 3 елементів, з крихітними значеннями, щоб не вимкнути час:

21 байт

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

Спробуйте в Інтернеті!




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.
Джонатан Фрех

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.