Codegolf — Реализация Take While

  • Автор темы Docanton
  • Обновлено
  • 21, Oct 2024
  • #1

Введение и кредит

Сегодня без причудливой прелюдии: Пожалуйста, реализуйте

 
 Example Input: [42, 14, 42, 43, 41, 4080622, 171480372]

Consider first element: 42
42 is even (21*2)
Put 42 into output list, output list is now [42]

Consider second element: 14
14 is even (7*2)
Put 14 into output list, output list is now [42,14]

Consider third element: 42
42 is even (21*2)
Put 42 into output list, output list is now [42,14,42]

Consider fourth element: 43
43 is not even (2*21+1)
Drop 43 and return the current output list

return [42,14,42]
 
.

Вариантом этого (с нетривиальной структурой данных) было задание на моем университетском курсе функционального программирования. Это задание закрыто и обсуждалось в классе, и у меня есть разрешение профессора опубликовать его здесь (я попросил явно).

Спецификация

Вход

Входными данными будет список (или эквивалентная концепция вашего языка) положительных целых чисел.

Выход

Результатом должен быть список (или эквивалентная концепция вашего языка) положительных целых чисел.

Что делать?

Ваша задача реализовать [14, 42, 2324, 97090, 4080622, 171480372] -> [14, 42, 2324, 97090, 4080622, 171480372] [42, 14, 42, 2324] -> [42, 14, 42, 2324] [7,14,42] -> [] [] -> [] [171480372, 13, 14, 42] -> [171480372] [42, 14, 42, 43, 41, 4080622, 171480372] -> [42, 14, 42] (language built-ins are allowed) with the predicate that the number under consideration is even (to focus on takewhile).

Таким образом, вы перебираете список от начала до конца, и пока условие (четное) выполняется, вы копируете его в список вывода, и как только вы нажимаете на элемент, который не делает условие истинным, вы прерываете операцию и выводите результат. (пошаговый пример ниже). Эта функциональность более высокого порядка также называется takeWhile ( [42,14] ).

Возможные угловые случаи

Порядок выходного списка по сравнению с входным списком не может быть изменен, например. [14,42,2] may not become takewhile .

Пустой список является допустимым входом и выходом.

Кто победит?

Это код-гольф, поэтому побеждает самый короткий ответ в байтах!

Разумеется, применяются стандартные правила.

Тестовые векторы

takewhile

Пошаговый пример

takewhile

#код-гольф #массив

Docanton


Рег
07 Mar, 2011

Тем
68

Постов
199

Баллов
569
  • 26, Oct 2024
  • #2

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

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
hH:2%0,?b&~b.hH;[].

s.:Mc?,.:{:2%0}a

Еще одна великолепная встроенная функция, которая в три раза превосходит языки игры в гольф без встроенной...

 

Саи


Рег
07 Apr, 2011

Тем
90

Постов
189

Баллов
649
  • 26, Oct 2024
  • #3

Хаскель, 13 байт

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 1&:v>::   v                >00g1+:4g.v
v-1_^#:>#<>$$\$1-:10p000p0-| -g01p00:<
>\:&:2%|                   @

\+1p4\< ^
 

number_of_values values(separated by a space) splits the input list into a pair of lists just before the first element where the predicate (-> 1&:v v-1_@#:@#< >\:&:2%| \+1p4\< ^ ) неверно. : f DEPTH IF BEGIN DUP 2 MOD DUP 1- IF SWAP . THEN UNTIL THEN ; takes the first element of the pair.

Альтернативная версия, 13 байт:

: f DEPTH IF ( if stack not empty ) 1 DEPTH 1 DO DEPTH 1- ROLL LOOP ( put 1 on bottom of stack ) DEPTH 0 DO ( loop over entire stack ) I PICK 2 MOD IF ( if stack[i] is odd ) DEPTH I LEAVE ( put range and exit loop ) THEN LOOP DO I ROLL ( roll eyes ) DROP LOOP ( iterate that range and remove ) THEN ;

: D DEPTH ; : f D IF 1 D 1 DO D 1- ROLL LOOP D 0 DO I PICK 2 MOD IF D I LEAVE THEN LOOP DO I ROLL DROP LOOP THEN ; is the opposite of 1 , то есть он разбивает список на первый элемент, где предикат истинен.

Конечно, есть еще

{~1&},

но это 14 байт.

 

Bm_marat


Рег
29 May, 2008

Тем
73

Постов
223

Баллов
648
  • 26, Oct 2024
  • #4

МАТЛ, 6 байт

{1&},

Попробуйте онлайн!

Объяснение

{ }, ||answer||

шестиугольник, 19

~ # evaluate input 1\ # push the number 1 onto the stack and move it under then input array { # start of loop body ~ # bitwise negate the input number (making odd numbers even and vice versa) & # take bitwise AND of input and the saved number (0 or 1) on stack . # duplicate result; filter loop will pop off the duplicate }, # run loop above over input array, select elements for which it returns true p # stringify and print filtered array ; # pop the number 0/1 off the stack

Читабельно:

~1\{~&.},p;

Попробуйте онлайн!

Вероятно, это можно сделать с помощью одного-двух байтов, но для этого может потребоваться какая-то действительно гениальная компоновка, которую будет легче найти с помощью грубой силы (даже если ее поиск может занять довольно много времени).

Объяснение высокого уровня

Программа в основном следует этому псевдокоду:

[28 14 7 0]

Это нарушает то, как Hexagony пытается прочитать число, когда STDIN пуст (он возвращает ноль). Большое спасибо Мартину за помощь в разработке этого подхода.

Полное объяснение

Я до сих пор не возился с Моно, чтобы получить Тимви. фантастическая эзотерическая IDE бегу, поэтому я попросил Мартина предоставить мне несколько полезных красивых фотографий!

Сначала немного о базовом управлении в Hexagony. Первый указатель инструкций (IP), единственный, используемый в этой программе, начинается в верхнем левом углу шестиугольного исходного кода и начинает двигаться вправо. Всякий раз, когда IP покидает край шестиугольника, он перемещается 2L% - map(%2, input) f - split_at(input, ^) hO - ^[0][:-1] rows towards the middle of the hexagon. Since this program uses a side length three hexagon, the IP will always be moving two rows when this happens. The only exception is if it moves off of the middle row, where it conditionally moves towards the top or bottom of the hexagon, depending on the value of the current memory edge.

Теперь немного об условных обозначениях. Единственные условия в Hexagony для потока управления: 2L%fhO , 2L% - map(%2, input) 1R@ - ^.index(1) < - input[:^] и средний край шестиугольника. Все они подчиняются постоянному правилу: если значение на текущей границе памяти равно нулю или отрицательному значению, поток управления перемещается влево, а если положительное, управление перемещается вправо. Скобки «больше» и «меньше» перенаправляют IP под углом шестьдесят градусов, а край шестиугольника определяет, к какой строке перейдет IP.

Hexagony также имеет специальную модель памяти, где все данные хранятся на краях бесконечной шестиугольной сетки. Эта программа использует только три ребра: одно для хранения двойки, одно для текущего считанного числа и одно для числа по модулю два. Это выглядит примерно так:

2L%1R@<

Я не буду подробно объяснять, где мы находимся в памяти в каждый момент объяснения программы, так что возвращайтесь сюда, если вас запутает, где мы находимся в памяти.

Разобравшись со всем этим, можно начать настоящее объяснение. Сначала мы заполняем ребро «2» в памяти цифрой 2, затем выполняем неактивную операцию и перемещаем указатель памяти вправо ( 0+2L%fhO ).

Далее мы начинаем основной цикл программы. Мы читаем первое число из STDIN, а затем выполняем условную операцию ( ->a{a.take_while &:even?} ). If there are no numbers left in STDIN, this reads a zero into the current memory edge, so we turn left onto the /⍨ , что завершает программу. В противном случае мы отскакиваем от зеркала, перемещаем указатель памяти назад и влево, оборачиваем шестиугольник, чтобы вычислить остаток от деления входных данных на 2, а затем нажимаем еще один условный оператор ( ∧\ ).

Если остаток был равен единице (т. е. число было нечетным), мы поворачиваем направо по синему пути, указанному выше, начиная с повторного выполнения нулевой операции, затем переносимся к нижней части шестиугольника, умножаем текущее ребро на 10, а затем добавляем восемь, отскочить от пары зеркал, снова выполнить то же умножение и сложение, получить 188 на текущем ребре, вернуться обратно к вершине шестиугольника, снова выполнить нулевую операцию и, наконец, завершить программу ( ~ ). This convoluted result was a happy accident, I originally had written a much simpler bit of logic, but noticed that I could remove it in favour of the no-op, which I thought was more in the spirit of Hexagony.

Если остаток был равен нулю, мы вместо этого поворачиваем налево по красному пути, указанному выше. Это заставляет нас перемещать указатель памяти влево, а затем печатать там значение (входное значение) в виде числа. Зеркало, с которым мы сталкиваемся, действует как неактивное из-за направления, в котором мы движемся ( 2| ). Then we hit the edge of the hexagon which acts a conditional with only one outcome, as the input value from before was already tested to be positive, so we always move towards the right (if you imagine yourself facing in the direction of the IP). We then multiple the input by 10 and add two, only to change direction, wrap around and overwite the new value with the ascii value of the capital letter M, 77. Then we hit some mirrors, and exit over the edge of the middle of the hexagon with a trampoline ( {⍵/⍨∧\~2|⍵} ). Поскольку 77 положительно, мы двигаемся вправо к низу шестиугольника и из-за батута пропускаем первую инструкцию ( ? "search for, on every line ä* "Any number of digits [13579] "Followed by an odd digit ¾ "Then the end of a word, .* "Followed by anything "(implicit) and replace it with nothing. ). We then multiply the current memory edge by 10 and add 8, getting 778. We then output this value mod 256 (10) as an ASCII character, which happens to be newline. Finally we exit the hexagon and wrap back around to the first эä*[13579]¾.* который переопределяет 778 следующим входным значением.

 

Isomia12


Рег
25 Oct, 2024

Тем
70

Постов
189

Баллов
539
  • 26, Oct 2024
  • #6

Желе, 5 байты

?\d*[13579]\b.*

Попробуйте онлайн! или проверить все тестовые случаи.

Как это работает

{ } e# define code block 1+ e# attach 1 at the end of the array _ e# duplicate 2f% e# modulo 2 of each entry 1# e# find index of first occurrence of 1 < e# slice before ||answer||

Питон 2, 43 42 байта

{1+_2f%1#<}

Функция изменяет свой аргумент на месте.

Спасибо @xnor за очень умный способ отыграть байт!

Проверьте это на идея.

 

DrateLesses


Рег
02 Dec, 2011

Тем
64

Постов
208

Баллов
558
  • 26, Oct 2024
  • #7

ред, 13

int[]f(int[]a)=>(a.TakeWhile(x=>x%2<1).ToArray());

Потому что настоящий программисты используйте стандартный текстовый редактор.

Принимает входные данные как одно целое число в каждой строке; выводит в том же формате.

Это просто находит первое нечетное число (число, оканчивающееся нечетной цифрой) и удаляет из этой строки до конца файла.

 

Fantom837


Рег
13 Dec, 2007

Тем
65

Постов
185

Баллов
530
  • 26, Oct 2024
  • #8

Кложур, 21 байт

1

Clojure наконец-то почти конкурирует! (благодаря тому, что задача встроена) Посмотреть онлайн https://ideone.com/BEKmez

 

Usegor


Рег
28 Mar, 2020

Тем
77

Постов
198

Баллов
603
  • 26, Oct 2024
  • #10

Р, 25 байт

1

Или эквивалентно

l ||answer||

05AB1E, 8 7 байт

lambda l:l[:[x%2for x in l+[1]].index(1)]

Объяснение

{.~2&|i.1: Input: s 2&| Take each value in s mod 2 i.1: Find the index of the first 1 {.~ Take that many values from s and return

Попробуйте онлайн

Предыдущее 8-байтовое решение

{.~2&|i.1:

Объяснение

[[H], Result]

Попробуйте онлайн

 

Andrey45


Рег
27 Sep, 2006

Тем
77

Постов
207

Баллов
642
  • 26, Oct 2024
  • #11

Мозг***, 263 байта

Я взял небольшой отрывок из здесь

H

Я бы дал объяснение, но даже я понятия не имею, как это работает.

Ожидает ввода в виде чисел, разделенных пробелами (например, :[H]rc. )

 

Pomeln


Рег
27 Sep, 2005

Тем
79

Постов
202

Баллов
597
  • 26, Oct 2024
  • #13

Ракетка, 22 байта

s. Output is an ordered subset of Input :Mc?, The concatenation of Output with a list M is Input .:{:2%0}a All elements of Output are even

; character is counted as 2 bytes.

Я раньше не видел использования Racket ни в одном из ответов по коду игры в гольф, которые я видел, поэтому мне пришлось сделать это хотя бы один раз!

 

Velass


Рег
13 Feb, 2011

Тем
77

Постов
208

Баллов
623
  • 26, Oct 2024
  • #14
Labyrinth , 14 байт. Входные и выходные данные представляют собой списки, разделенные переводом строки (хотя в принципе на входе может использоваться любой нецифровой разделитель). Попробуйте онлайн! Вероятно, это самая компактная программа-лабиринт, которую я когда-либо писал. Интересно, что объяснение Обычный учебник по Лабиринту: модель памяти представляет собой стек (на самом деле их два, но для этой программы нам понадобится только один), который хранит целые числа произвольной точности и изначально содержит (неявное) бесконечное количество нулей. Инструкций по потоку управления нет. Вместо этого движение указателя инструкции (IP) определяется расположением кода (пространства считаются «стенами» и не могут быть пересечены IP). Обычно код должен напоминать лабиринт, где IP следует по прямым коридорам и изгибается, но всякий раз, когда он достигает перекрестка, это действует как условие, когда новое направление IP определяется на основе текущего состояния. Правила выбора направления сводятся к следующему: если вершина стека равна нулю, IP продолжает двигаться вперед; если вершина положительна, IP поворачивается вправо; если верх отрицательный, IP поворачивается влево. Если одно из этих направлений заблокировано стеной, IP вместо этого принимает противоположное направление. Это означает, что с программами без четких коридоров обычно невероятно сложно работать, поскольку каждая отдельная команда будет действовать как связующее звено. Тот факт, что в данном случае это сработало, является своего рода чудом. IP начинается с первого непробельного символа в порядке чтения (Основной поток программы представляет собой один цикл по периметру: как это бывает, мы знаем, что вершина стека после этого равна нулю, так что IP гарантированно не для поворота к центру, с другой стороны, используются как условные выражения, когда IP может двигаться к центру, так что давайте посмотрим на код в цикле: И тогда цикл начинается заново. Возникает вопрос, почему поскольку EOF возвращается как. Теперь мы хотим завершить работу, когда (в отличие от by, и мы даже избавились от ), но если ввод четный, это просто завершает программу с (тихой) ошибкой деления на ноль. Следовательно, другой код. простой цикл, который вообще не допускает никакого ветвления
 

Kyropatka777


Рег
30 Dec, 2019

Тем
74

Постов
201

Баллов
601
  • 26, Oct 2024
  • #15
Brachylog , 19 16 байт Объяснение Сегодня я научился хитрому трюку (который использовался в 19-байтовом ответе): добавлять элемент в начало. Первый означает «Выходные данные — это результат с дополнительным элементом в начале, а первый элемент выходных данных — », тогда как другой — это просто «Выходные данные — это объединение
 

Dudgirege


Рег
25 Feb, 2008

Тем
68

Постов
189

Баллов
569
  • 26, Oct 2024
  • #16
J, 10 байт. Пояснение Python, 41 байт. Усекает значения по модулю, ставится в конце.
 

Japssoary89


Рег
25 Oct, 2024

Тем
80

Постов
190

Баллов
610
  • 26, Oct 2024
  • #17
C#, 50 байт CJam, 11 байт Спасибо @Dennis за два исправления и потерю одного байта! Это блок кода (эквивалент функции; разрешен по умолчанию), который ожидает входной массив в стеке и оставляет выходной массив в стеке. Попробуйте онлайн! Пояснение Retina , 17 байт. Конечный перевод строки имеет значение. Входные и выходные данные представляют собой списки, разделенные пробелами. Попробуйте онлайн! Это простая подстановка в регулярном выражении, она соответствует первому нечетному числу (т. е. числу, оканчивающемуся нечетной цифрой) и, если возможно, предшествующему ему пробелу, а также всему после него, и заменяет его пустой строкой, т. е. всеми элементами оттуда далее удаляются из ввода. Как указывает Leaky Nun, взяв список в двоичном виде, мы можем сэкономить 6 байт, но это кажется немного обманным, поэтому я, вероятно, продолжу считать десятичную версию: JavaScript (Firefox 30-57), 30 байт V, 13 байт Попробуйте онлайн! Объяснение: Удобно, что один и тот же код работает для одновременной проверки всех тестовых случаев.
 

BorisIZ


Рег
02 Aug, 2005

Тем
86

Постов
211

Баллов
651
  • 26, Oct 2024
  • #19
Руби, 25 байт, кажется, я проиграю...
 

Svkvarinod


Рег
09 Jun, 2016

Тем
77

Постов
213

Баллов
608
  • 26, Oct 2024
  • #20
Пайк, 8 байт Исправлен интерпретатор, используйте другие ссылки Использует метод Денниса, за исключением того, что моя функция Split_at включает изменение - возможно, ошибка Или с исправлением ошибки, 7 байт Попробуйте здесь! Или после второго исправления 6 байт. Попробуйте здесь! Пояснение: GolfScript, 11 байт. Это полная программа GolfScript, которая считывает строковый литерал массива GolfScript (например, Попробуйте онлайн. (Также: Расширенная версия с тестовым оборудованием. Версия без игры в гольф с комментариями: Это решение основано на GolfScript. Таким образом, Таким образом, задача состоит в том, чтобы создать фильтр, который выбирает четные числа до тех пор, пока не найдет первое нечетное, а затем вообще не выбирает никаких чисел. Решение, которое я использовал, состоит в том, чтобы заменить постоянный бит-. маска
 

Nokiaasha302


Рег
05 Nov, 2019

Тем
79

Постов
194

Баллов
629
  • 26, Oct 2024
  • #21
Форт, 114 байт На самом деле в Форте нет списков. Параметры должны помещаться в стек в обратном порядке, как это обычно бывает в Форте. Результат останется в стеке в том же порядке. по какой-то причине не работает на Ideone, но работает на repl. Новая строка нужна, чтобы убрать какую-то двусмысленность. Попробуйте онлайн Ungolfed, с with?

N % 2

N is lot simpler:

N % 2

  • N in this case), moving east.

1

0 and N % 2 0 and takewhile(odd) ? Read decimal integer N from STDIN, or 0 at EOF. : Duplicate. Since this is just a corner, the IP always turns south. ` Negate the copy of the input (i.e. multiply by 1). At EOF, the result is still zero and the IP keeps moving south into the @. Otherwise, the top of the stack is now negative, and the IP turns east. # Push the stack depth (i.e. 2). Again, this is a corner, and the IP is forced to turn south. % Computer (-N % 2), which is identical to (N % 2) to determine the parity of the input. If input was odd, this gives 1, and the IP turns west into the @. Otherwise, the result is 0 and the IP keeps moving south, continuing the loop. ; Discard the 0. This is a corner, so the IP is forced to turn west. ! Print (and discard) N. The top of the stack is now one of the implicit zeros at the bottom, so the IP keeps moving west. \ Print a linefeed. The IP is forced to turn north in the corner. "" Two no-ops. The top of the stack is still zero, so the IP keeps moving north. terminates the program, or it might keep moving around the perimeter.

@

% is so much simpler. There's two reasons:

  • ` (which is even), we don't need a separate EOF check. The list would be cut off at that point anyway.
  • " is ! >v ^>v ^@v ^<< ), which means instead of conditional control flow we can simply divide the other copy ? ?:# " % \!/ : if the input is odd, that just leaves takewhile(odd) ?: "`# "@% \!; (so we don't need λ

(λ(n)(takef n even?))

<x%R2Q1

2 432 1 is shorter than >>>>>>,[>>>>>>,]>++++[<++++++++>-]>>>>>+>>>>>>>++++[<++++++++>-]<<<<<<<[<<<<<<]>>>>>>[[>>>>>>>++++[<-------->-]<]<<<<<<[->>>+<<<]>>>[-<+<<+>>>]<>>+>+<<<[-[->]<]+>>>[>]<[-<]<[-]<-[<[<<<<<<]>>>>>>.>>>>>>[>[-]++++[<++++++++>-]<.>>>>>>]>++++[-<++++++++>]<.[-]]>>>>>>] v # for each y in input yÈi # if y is even yˆ # push y to global array ëq # else terminate program # implicitly print global array " vyÈiyˆëq ".

[ # infinite loop start DÉO # count odd numbers _ # push negative bool (turning 0->1, X->0) # # if true (no odd numbers exist), break out of loop and implicitly print ¨ # else, remove last element from list

[DÉO_#¨ ||answer||

(y=scan())[!cumsum(y%%2)]

x=scan() x[!cumsum(x%%2)] up to the index of the first occurrence of an odd number. The index is found by looking for a f=lambda x:x and~x[0]%2*x and x[:1]+f(x[1:]) #(take-while even? %) . To guard against no odd number being found, a /[13579]$/,$d

def f(x): while"1'"in`map(bin,x)`:x.pop() ||answer||

Ḃœp⁸Ḣ Main link. Argument: A (array) Ḃ Bit; yield 1 for odd integers, 0 for even ones. ⁸ Yield A. œp Partition A, splitting at 1's in the bit array. This yields a 2D array of runs of even integers. Ḣ Head; extract the first chunk.

Ḃœp⁸Ḣ ||answer||

u Q keep applying to input until invariant: PW drop last element if... s%R2G ...any one is odd, G is the argument originally given the value of input

uPWs%R2 ||answer||

? ||answer||

!

2<M\>$

, 11

{/!

.8/\8.@ division remainder from dividing with 2

/"%> negate

@ AND-scan (turns off from first 0)

?< select where

2.}

Mod \ / Input | 2

<

>

side_length - 1

while (read number is not zero) { if (number is even) print number; } ||answer||

2 . } < @ > % ? < { > $ " / \ M ! 8 ; ) and prints out the same array with the first odd element and everything after it removed:

2.}<@>%?<{>$"/\M!8;

)

t % Input array implicitly. Duplicate o % Parity of each entry. Gives 0 for even entries, 1 for odd Ys % Cumulative sum ~ % Logical negate. Gives true for the first run of even entries, and then false ) % Use this as logical index into the original array. Implicitly display

toYs~) filter operator, which runs the contents of the code block on each element of an array, and selects the elements of the array for which the code in the block returns a true (i.e. non-zero) value on top of the stack.

takeWhile even would select all odd numbers in an array, and span

break (used to extract the lowest bit of each input number) with a variable on the stack that stores the result (0 or 1) of the previous filter loop iteration (and is initialized to 1 before the loop). Thus, as soon as the filter returns 0 once, the bitmask also gets set to 0, preventing the filter from ever returning 1 again.

fst.break odd

fst

Эта программа (моя предыдущая попытка) печатает результаты до тех пор, пока не достигнет нечетного числа. Все оставшееся (не забранное) останется в стеке.

even

Ошибка, если только четные целые числа

 

Андрей урм


Рег
26 Aug, 2011

Тем
65

Постов
207

Баллов
572
  • 26, Oct 2024
  • #22

Бефунге, 35 байт

Этот код обрабатывает числа от 0 до 65535.

span

Формат ввода:

fst.span even

Вот версия, которая отображает значения в конце процесса:

#~TakeWhile~EvenQ&

Вы можете протестировать код здесь, но вам придется добавить завершающую строку с пробелами, как указано в этой интерпретации:

«Тор кода имеет размер исходной программы. Вставьте больше

строк или конечного пробела, если данные будут помещены за конец кода».
Я не знаю, приемлемо ли это, так как я не учитывал этот конец в подсчете байтов.


Примечание: похоже, что, поскольку я храню число в коде, интерпретатор не позволит этой программе запуститься дважды правильно. Вам придется перезагрузить его. Как это работает:

Интерпретатор следует за стрелками и пропускает инструкцию при пересечении знака «#».

Серые точки — это тест, а красная линия удаляет ненужные переменные из стека.

 

Сандра184


Рег
13 Nov, 2012

Тем
66

Постов
169

Баллов
519
Тем
403,760
Комментарии
400,028
Опыт
2,418,908

Интересно