Качка, Качка, Йосиф


49

Дано масив Integer:

  1. Почніть з першого числа
  2. Перейти вперед n позицій, де n - значення поточної позиції
  3. Видаліть поточну позицію, зробивши наступну позицію поточною.
  4. Перейдіть до кроку 2, поки не залишиться одне число
  5. Роздрукуйте це число

Правила

Обрізка масиву (наступне число після останнього числа в масиві - це перше число).

Нуль знімає себе (очевидно).

Негативні числа заборонені як введення.

Випробування

[1] => 1
[1,2] => 1
[1,2,3] => 3
[1,2,2] => 1
[1,2,3,4] => 1
[6,2,3,4] => 4
[1,2,3,4,5] => 5
[0,1] => 1
[0,0,2,0,0] => 0

Покроковий приклад

[1,4,2,3,5]
 ^          start from the first position
   ^        jump 1 position (value of the position)
[1,  2,3,5] remove number in that position
     ^      take next position of the removed number (the 'new' 'current' position)
         ^  jump 2 positions
[1,  2,3  ] remove number in that position
 ^          take next position (looping on the end of the array)
     ^      jump 1 position
[1,    3  ] remove number in that position
       ^    take next position (looping)
 ^          jump 3 positions (looping on the end of the array)
[      3  ] remove number in that position
print 3

Приклад №2

[4,3,2,1,6,3]
 ^            start from the first position
         ^    jump 4 positions
[4,3,2,1,  3] remove number in that position    
           ^  take next position
     ^        jump 3 positions
[4,3,  1,  3] remove number in that position    
       ^      take next position
           ^  jump 1 positions
[4,3,  1    ] remove number in that position    
 ^            take next position
   ^          jump 4 positions
[4,    1    ] remove number in that position    
       ^      take next position
 ^            jump 1 position
[      1    ] remove number in that position
print 1

Це , найкоротша відповідь у байтах виграє!


14
Приємний перший виклик!
Луїс Мендо

2
@LuisMendo Так. Проблеми "пропустити як ..."
J42161217

2
@Jenny_mathy Я не думав, що буде подібний, але, як сказав Луїс, масив обгортки робить цікавим завданням для гольфу. Я думаю: /
обмінний потік

3
@EriktheOutgolfer Насправді не дура. Елементи там не відрізняються і розмір кроку фіксується. Луїс набагато ближче, але все-таки досить інший, я думаю.
Мартін Ендер

3
Чи потрібно насправді надрукувати підсумковий номер, чи може просто повернути його? Чи потрібно фактично повертати число, чи він може просто працювати на масиві на місці, щоб після запуску функції масив містить просто число?
iamnotmaynard

Відповіді:



7

Haskell , 54 50 48 байт

f[x]=x
f(x:r)=f$snd<$>zip r(drop(x+1)$cycle$x:r)

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

Пояснення:

  • f[x]=x: Якщо даний список є однотонним списком, поверніть його елемент.
  • f(x:r)=f$ ...: В іншому випадку рекурсивно застосовується fдо наступного списку:
    • Елементи поточного списку циклічно нескінченно ( cycle$x:r),
    • з x+1видаленими першими елементами ( drop(x+1)$),
    • і підрізаний до довжини r. ( snd<$>zip rє коротшою альтернативою take(length r)).

Попередня версія 54 байтів:

f=(%)=<<head
_%[x]=x
n%(x:r)|n<1=f r|s<-r++[x]=(n-1)%s

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



6

MATL , 21 байт

1`yy)+ynX\[]w(5Mynq]x

Спробуйте в Інтернеті! Або перевірити всі тестові випадки .

Пояснення

1        % Push 1: current position in the array
`        % Do...while
  yy     %   Duplicate top two elements in the stack. Takes input implicitly
         %   in the first iteration.
         %   STACK: array, position, array, position
  )      %   Get specified entry in the array
         %   STACK: array, position, selected entry
  +      %   Add
         %   STACK: array, position (updated)
  y      %   Duplicate from below
         %   STACK: array, position, array
  n      %   Number of elements of array
         %   STACK: array, position, number of elements or array
  X\     %   1-based modulus
         %   STACK: array, position (wrapped around)
  []     %   Push empty array
         %   STACK: array, position, []
  w      %   Swap
         %   STACK: array, [], position
  (      %   Write value into specified entry in array. Writing [] removes
         %   the entry
         %   STACK: array (with one entry removed)
  5M     %   Push latest used position. Because of the removal, this now
         %   points to the entry that was after the removed one
         %   STACK: array, position
  y      %   Duplicate from below
         %   STACK: array, position, array
  n      %   Number of elements of array
         %   STACK: array, position, number of elements of array
  q      %   Subtract 1
         %   STACK: array, position, number of elements of array minus 1
]        % End. If top of the stack is nonzero, proceed with next iteration
         % STACK: array (containing 1 entry), position
x        % Delete. Implicitly display
         % STACK: array (containing 1 entry)

1
Примітка: використання обертів списку замість збереження вказівника, ймовірно, зробить це значно коротше.
Ерік Аутгольфер

1
@Erik Дякую Але тепер, коли я додав пояснення, я думаю, що я залишу це так
Луїс Мендо

Ну, ви завжди можете видалити пояснення, воно збережеться в історії :)
Erik the Outgolfer


5

CJam , 15 байт

l~_,({_0=m<1>}*

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

Пояснення

Замість того, щоб відслідковувати вказівник, я просто циклічно зміщую масив, щоб поточний елемент завжди був спереду.

l~     e# Read and evaluate input.
_,(    e# Get its length L and decrement to L-1.
{      e# Run this block L-1 times...
  _0=  e#   Get the first element X.
  m<   e#   Rotate the array left by X positions.
  1>   e#   Discard the first element.
}*
       e# The final element remains on the stack and gets printed implicitly.

Приємна альтернатива, яка, на жаль, не економить жодних байтів:

l~_{;m<1>_0=}*;

5

Мозок-Флак , 88 байт

([[]]()){({}<(({})){({}<({}<([]){({}{}<>)<>([])}{}>)<>{({}[<>[]])<>}<>>[()])}{}{}>())}{}

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

Пояснення

([[]]())                      Push negative N: the stack height - 1
{({}< … >())}{}               Do N times
     (({}))                     Duplicate M: the top of the stack
     {({}< … >[()])}{}          Do M times 
                                  Rotate the stack by 1:
          ({}< … >)               Pop the top of the stack and put it back down after
          ([]){({}{}<>)<>([])}{}  Pushing the rest of the stack on to the other one, in reverse, with the stack height added to each element (to ensure that all are positive)
          <>{({}[<>[]])<>}<>      Push the rest of the stack back, unreversing, and subtracting the stack height from each element
                      {}        Pop the top of stack

1
Дуже дивний гольф, але ось він у 88 байтах .
Пшеничний майстер

1
@WheatWizard Приємно, на диво я спробував щось подібне раніше.
H.PWiz

Я ніколи не можу знати, як люди можуть кодувати так! чи є перекладач псевдокоду чи щось таке?
зворотний потік

1
@workoverflow ні, це чесно простіше, ніж це виглядає. До того, як я насправді почав, це було дуже непросто, але коли команди такі прості, це легко вивчити.
H.PWiz

5

Python 2 , 55 байт

def f(a):
 while a[1:]:l=a[0]%len(a);a[:]=a[-~l:]+a[:l]

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

Виводиться як однотонний список, як це дозволено за замовчуванням . Зберегли кілька байтів завдяки Деннісу , нагадуючи, що дозволяється змінювати аргумент функції.

Як це працює

  • def f(a)- Визначає функцію з параметром a.

  • while a[1:]:- У той час, aколи перший елемент, який видаляється, є трибунним, запустіть блок коду для виконання. Список з одним або декількома елементами є правдоподібним, а порожні списки - хибними в Python, отже, це зупиняється, коли aдосягне довжини 1.

  • l=a[0]%len(a)- Візьміть перший елемент і отримайте решту його ділення на довжину a. Призначте результат l.

  • a[:]=a[-~l:]+a[:l]- Поверніть елементи aліворуч lта видаліть перший, призначаючи це на aмісце.


Python 2 , 63 байти

f=lambda a,i=0:a[1:]and f(a,a.pop(((a*-~i)[i]+i)%len(a))+1)or a

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

Хоча і довше, це здається набагато елегантнішим. Також дякую овам за допомогу у чаті.


1
Не могли б ви зробити щось на кшталт a,*b=input()(python3) і зберегти кілька байтів? Однак я не впевнений, як це вплине lі на зріз
стрижень

1
@Rod Я не думаю, що мені потрібно також оцінити вкладення в Python 3
Містер Xcoder

4

Желе , 7 байт

ṙḷ/ḊµḊ¿

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

Повна програма.


3
Це ḷ/чорт розумно.
Містер Xcoder

Чи можете ви додати пояснення, будь ласка? Зараз я дивився на Quicks і Atoms на пов'язаних GIT-сторінках, і +1-ed на основі цього, але можу уявити, що не всі мають пацієнтів, щоб зробити те саме. ;)
Кевін Круїссен




3

Математика, 36 байт

використовує алгоритм Мартіна

#//.l:{x_,__}:>Rest@RotateLeft[l,x]&

-5 байт від Misha Lavrov && Martin Ender

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


1
Ви можете зберегти два байти за допомогою шаблону, щоб вибрати перший елемент #//.{x_,y__}:>Rest@RotateLeft[{x,y},x]&. (Це припиняється, коли є лише один елемент, оскільки він {a}більше не відповідає шаблону {x_,y__}.)
Міша Лавров

1
@MishaLavrov зараз не може перевірити, але ви, ймовірно, можете скоротити це ще більше, скинувши y, викликувши весь список lі використовуючи lзамість цього {x,y}.
Мартін Ендер

1
@MartinEnder Ви маєте на увазі так - #//.l:{x_,__}:>Rest@RotateLeft[l,x]&?
Міша Лавров

1
@MishaLavrov так.
Мартін Ендер

3

J , 21 17 байт

-4 байти завдяки FrownyFrog

((1<#)}.{.|.])^:_

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

Оригінал:

([:}.{.|.])^:(1<#)^:_

Як це працює:

^:_ повторюйте, поки результат не перестане змінюватися

^:(1<#) якщо довжина списку більше 1

{.|.] поверніть список ліворуч першим його пунктом

[:}. опустити перший елемент і зафіксувати виделку

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


@ FrownyFrog Спасибі, я цього не пробував - це набагато краще!
Гален Іванов

3

JavaScript (ES6), 54 60 байт

Збережено 1 байт завдяки виправленій версії @Shaggy
(+6 байт)

Змінює вхідний масив , який зводиться до одинарного.

f=(a,p=0)=>1/a||f(a,p=(p+a[p%(l=a.length)])%l,a.splice(p,1))

Тестові справи

Як?

Ми рекурсивно застосовуємо алгоритм, описаний у виклику. Тільки умова зупинки 1/aможе здатися трохи дивною. При застосуванні арифметичного оператора:

  • Масиви з більш ніж одного елемента примусові NaNі 1/NaNтакож є NaN(хибними).
  • Масиви з рівним цілим числом примусові до цього цілого числа, ведучи до одного 1/0 = +Infinityабо 1/N = positive floatдля N> 0 (обидва трити).
f = (a, p = 0) =>                 // a = input array, p = pointer into this array
  1 / a ||                        // if a is not yet a singleton:
    f(                            //   do a recursive call with:
      a,                          //     a
      p = (                       //     the updated pointer
        p + a[p % (l = a.length)] //
      ) % l,                      //
      a.splice(p, 1)              //     the element at the new position removed
    )                             //   end of recursive call

Бачачи, як spliceмодифікує оригінальний масив, ви могли зробити f=(a,p=0)=>1/a||f(a,p=p+a[p]%a.length,a.splice(p,1))за 52 байти
Shaggy

здається, це не дає правильного результату для другого крокового прикладу, f=(a,p=0)=>1/a?a:f(a,p=(p%a.length+a[p%a.length])%a.length,a.splice(p,1))це нормально, але може бути оптимізовано
Nahuel Fouilleul

@NahuelFouilleul На жаль Я подумав у якийсь момент, що круглі дужки навколо p+a[p]можна видалити. Що - звичайно - не так. Дякуємо, що повідомили про це!
Арнольд

Дивіться цей консенсус , який @Neil довів до мене тут .
Кудлатий

@Shaggy О, бачу. Дякую! (Я пропустив ваше посилання TIO 1-й раз ...)
Арнольд


3

Java 8, 79 байт

Ця лямбда приймає Stack<Integer>та повертає intабо Integer.

l->{for(int i=0,s=l.size();s>1;)l.remove(i=(i+l.get(i%s))%s--);return l.pop();}

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

Безумовно

l -> {
    for (
        int i = 0, s = l.size()
        ; s > 1
        ;
    )
        l.remove(
            i = (i + l.get(i % s)) % s--
        );
    return l.pop();
}

Подяка

  • -2 байти завдяки Нахуелю Фуле

1
i%=sможе бути видалений, якщо буде l.get(i)зміненоl.get(i%s)
Nahuel Fouilleul

2

Pyth , 9 байт

.WtHt.<Zh

Спробуйте тут!

Це виводить результат у вигляді однотонного списку, як це дозволено за замовчуванням .

Як це працює

.WtHt.<Zh ~ Full program.

.W        ~ Functional while. It takes three arguments, two functions: A and B
            and a starting value, which in this case is automatically assigned
            to the input. While A(value) is truthy, value is set to B(value).
            Returns the ending value. A's argument is H and B's is Z.
  tH      ~ A (argument H): Remove the first element of H. A singleton list
            turns into [], which is falsy and thus breaks the loop. Otherwise,
            it is truthy and the loops goes on until the list reaches length 1.
     .<Zh ~ B (argument Z): Cyclically rotate Z by Z[0] places, whereas Z[0]
            represents the first element of Z.
    t     ~ And remove the first element.

Примітка. Якщо ви не хочете бачити ці дужки, просто додайте hабо eперед усім кодом.


2

Швидкий , 87 байт

func f(a:inout[Int]){var i=0,c=0;while(c=a.count,c>1).1{i=(i+a[i%c])%c;a.remove(at:i)}}

Повертається як однотонний список шляхом зміни введення . Спробуйте в Інтернеті!

Пояснення

func f(a:inout[Int]){
  var i=0,c=0;            // Set the index i to 0
  while(c=a.count,c>1).1{ // While the length of the list > 0:
    i=(i+a[i%c])%c;       //  Add a[i] to i and loop back using modulo
    a.remove(at:i)        //  Remove a[i]
  }
}

2

Перл 6 , 46 45 байт

(-1 байт завдяки Бреду Гілберту)

{($_,{(|$_ xx*)[.[0]+(1..^$_)]}...1)[*-1][0]}

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

($_, { ... } ... 1)генерує послідовність списків, починаючи зі списку введення $_, кожен наступний елемент, що генерується виразом дужки, і закінчується, коли список smart- 1match --ie, має довжину 1. Послідовність [* - 1]отримує кінцевий елемент, і остаточний [0]виймає єдиний елемент із цього списку одиночних.

(|$_ xx *)створює плоску, нескінченну копію поточного елемента. Цей список індексується діапазоном, .[0] + (1 ..^ $_)щоб отримати черговий кінцевий список із серії.


1
розум підірваний Oo
Адріан

[*-1][0]можна об'єднати в [*-1;0]збереження байта. Також 1..$_-1краще писати як 1..^$_знову збереження байта.
Бред Гілберт b2gills

@ BradGilbertb2gills Я спробував [*-1;0], але, схоже, якимось чином не еквівалентний. Потім функція повертає список, а не число.
Шон

Це не зупиняє 1..^$_ оптимізацію
Бред Гілберт b2gills

1

Perl 5 , 47 43 41 + 2 ( -ap) = 43 байти

$\=splice@F,($_+=$F[$_%@F])%@F,1while@F}{

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

Вводить дані як пробіли, розділені цифрами.


здається, це не зовсім так, як це робиться крок за кроком, але це довше$x%=@F,splice@F,$x=($x+$F[$x])%@F,1while$#F;$_="@F"
Nahuel Fouilleul

1
wow oO Потрібно підняти мою гру.
Адріан



1

Java 8 , 325 байт

Гольф:

static void n(Integer[]j){Integer[]h;int a=0;h=j;for(int i=0;i<j.length-1;i++){if(h.length==a){a=0;}a=(a+h[a])%h.length;h[a]=null;h=m(h);}System.out.print(h[0]);}static Integer[] m(Integer[]array){Integer[]x=new Integer[array.length-1];int z=0;for(int i=0;i<array.length;i++){if(array[i]!=null){x[z]=array[i];z++;}}return x;}

Безголівки:

 interface ArrayLeapFrog {
static void main(String[] z) throws Exception {
    Integer[] j = {6, 2, 3, 4};
    n(j);
}

static void n(Integer[] j) {
    Integer[] h;
    int a = 0;
    h = j;
    for (int i = 0; i < j.length - 1; i++) {
        if (h.length == a) {
            a = 0;
        }
        a = (a + h[a]) % h.length;
        h[a] = null;
        h = m(h);
    }
    System.out.print(h[0]);
}

static Integer[] m(Integer[] array) {
    Integer[] x = new Integer[array.length - 1];
    int z = 0;
    for (int i = 0; i < array.length; i++) {
        if (array[i] != null) {
            x[z] = array[i];
            z++;
        }
    }
    return x;
  }
}

4
Ласкаво просимо! Пара порад: Тут не потрібно рахувати staticключові слова. Зазвичай мультиметодні рішення реалізуються як нестатичні члени класу, і mainстворюють екземпляр для тестування. Крім того, якщо ви це зробите таким чином, ви підтримуєте Java 7 і можете подати просто рішення на Java. Для подальшої довідки формат введення має тенденцію бути досить гнучким, так що, наприклад, ви можете вибрати введення даних як List(що дуже корисно для цієї проблеми).
Якоб

1

APL + WIN, 36 байт

¯1↑⍎¨(1⌈¯1+⍴v←,⎕)⍴⊂'v←(1<⍴v)↓v[1]⌽v'

Пояснення:

Підказки для введення екрана.

'v←(1<⍴v)↓v[1]⌽v' Loop logic as a string

 (1<⍴v)↓ only drop the first when number of elements n>1

 (1⌈¯1+⍴v←,⎕)⍴⊂ create a nested vector of logic of length 1 max n-1

 ⍎¨ execute each element of the nested vector in turn

¯1↑ take answer from executing final element

1

Python 2, 61 байт

def f(x):
 while x[1:]:y=x[0]%len(x);x=x[y+1:]+x[:y]
 print x

1
Я знаю, що існує маса відповідей python, але я подумав, що міг би також додати свій власний.
Rɪᴋᴇʀ

1

JavaScript, 58 56 59 байт

let f =

a=>{for(i=0,k=a.length;k>1;)i+=a[i%=k],a.splice(i%=k--,1)}
<h2>Test</h2>
Enter or paste a valid array literal within square brackets and click Run.
<blockquote>
   <input id = "array" type="text" length="20">
   <button type="button" onclick="run()">Run</button>
</blockquote>
Result: <pre id="o"></pre>

<script>
    function run() {
       let a = JSON.parse(array.value);
       f(a);
       o.textContent = a;
    }
</script>

Повертає результат як єдиний елемент, що залишився у вхідному масиві, який оновлюється на місці.

Два байти збережено, використовуючи оператор, відокремлений комою, а не блок-заяву в тілі циклу for! Три байти, втрачені для пропуску з елемента, видаленого в кінці масиву (:

Менше гольфу:

a => {
    for(i=0,k=a.length;k>1;) // once less than array length
        i+=a[i%=k],          // the new index
        a.splice(            // delete an element
           i%=k--,           // ensuring index is within array,
                             // and post decrement loop count
           1
        )
}

Це, здається, дає неправильну відповідь [3, 5, 7, 9].
Ніл

Неправильно для [3,5,7,9]. Очікуване значення 5
edc65

Функція не повертає значення, я не впевнений, чи правильний підрахунок байтів, враховуючи це, оскільки він не може працювати над собою ...
Брайан Х.

@ edc65 та Ніл, дякую - індекс елемента, видаленого в кінці масиву, не коригувався до початку скороченого масиву.
traktor53

@BrianH. функція модифікує свій параметр, існує консенсус щодо цього codegolf.meta.stackexchange.com/a/4942/21348
edc65

1

Мозок-Флак , 104 байти

H.PWiz має більш короткий відповідь тут , що я допоміг зробити, ви повинні перевірити його.

([[]]()){({}()<(({})){({}[()]<({}<(([])<{{}({}<>)<>([])}{}<>>)<>>)<>{({}[()]<({}<>)<>>)}{}<>>)}{}{}>)}{}

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

Пояснення

([[]]())   #Push 1 minus stackheight
{({}()<    #N times
 (({}))    #Get a copy of the top
 {({}[()]< #N times
  ({}<(([])<{{}({}<>)<>([])}{}<>>)<>>)<>{({}[()]<({}<>)<>>)}{}<>
           #Roll the top to the bottom (From the wiki)
 >)}{}     #End loop
 {}        #Remove one value
>)}{}      #End loop

Я думав, що буду змагатися . Тоді я зрозумів, що моя майже точно така ж, як і ваша , крім іншого "верхнього рулону"
H.PWiz

Я побачив, що ;). Використовувати той факт, що все негативно, досить розумно.
Пшеничний майстер


1

R , 111 117 126 байт

Завдяки @Giuseppe за те, що виграв 11 байт, змінивши цикл часу, отримав ще 4, видаливши функцію та прочитавши введення користувача безпосередньо.

Я не відчуваю себе чудово щодо того, що потрібно було дістатися - я впевнений, що існує більш елегантне рішення.

i=scan();m=1;while((l=sum(i|1))-1){j=i[m];p=`if`(j+m>l,j%%l+!m-1,j+m);p=`if`(!p,m,p);i=i[-p];m=`if`(p-l,p,1)};i

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

Невикористаний код

i=scan()
m=1
while((l=sum(i|1))-1){
  j=i[m]
  p=`if`(j+m>l,j%%l+!m-1,j+m)
  p=`if`(!p,m,p)
  i=i[-p]
  m=`if`(p-l,p,1)
}
i

117 байт - зауважте, що оскільки це рекурсивна функція, ім'я f=потрібно включати
Джузеппе

1
Я вважав це досить важким завданням із мовою на основі 1-індексу без обертання масивів; це потенційно на 1-3 байти коротше з whileциклом, я думаю.
Джузеппе


мій попередній 115 байт був недійсним, оскільки ми обоє забули f=частину рекурсивної функції. :(
Джузеппе

Я оновив старий бал і новий бал, щоб відобразити рекурсивність :) З циклу "while" я зіграв ще 4 байти за допомогою сканування.
Марк
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.