Введение и кредит
Сегодня без фантазии прелюдии: Пожалуйста реализации takewhile
.
Вариант этого (нетривиальной структуры данных) был заданием на моем курсе функционального программирования в университете. Это задание теперь закрыто и обсуждалось в классе, и у меня есть разрешение моего профессора опубликовать его здесь (я спросил явно).
Спецификация
вход
Входными данными будет список (или эквивалентная концепция вашего языка) положительных чисел.
Выход
Выходными данными должен быть список (или эквивалентная концепция вашего языка) положительных целых чисел.
Что делать?
Ваша задача - реализовать takewhile
(встроенные языковые модули допустимы) с предикатом, что рассматриваемое число является четным (сосредоточиться на takewhile).
Таким образом, вы перебираете список от начала до конца, и пока условие (четное) выполняется, вы копируете в выходной список и, как только вы нажимаете элемент, который не выполняет условие, вы прерываете операцию и вывод (пошаговый пример ниже). Эта функциональность более высокого порядка также называется takeWhile ( takewhile
).
Потенциальные угловые случаи
Порядок списка вывода по сравнению со списком ввода не может быть изменен, например, [14,42,2]
может не стать [42,14]
.
Пустой список является допустимым входом и выходом.
Кто выигрывает?
Это код-гольф, поэтому выигрывает самый короткий ответ в байтах!
Стандартные правила применяются конечно.
Тестовые векторы
[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]
Пошаговый пример
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]
Ответы:
Mathematica, 18 байт
Еще одно великолепное встроенное устройство, которое в 3 раза превосходит языки игры в гольф без встроенного ...
источник
Haskell, 13 байт
span
разбивает входной список на пару списков непосредственно перед первым элементом, где предикат (->even
) равен false.fst
занимает первый элемент пары.Альтернативная версия, 13 байт:
break
является противоположностьюspan
, т. е. разделяет список на первый элемент, где предикат имеет значение true.Конечно, есть также
но это 14 байтов.
источник
MATL , 6 байтов
Попробуйте онлайн!
объяснение
источник
to~Y<)
тоже работает, но мне больше нравится этот :-)Гексагония , 19
Удобочитаемый:
Попробуйте онлайн!
Вероятно, это может быть игра в гольф одним или двумя байтами, но это может потребовать некоторой действительно изобретательной компоновки, которую можно было бы легче найти с помощью грубой силы (даже если это может занять довольно много времени).
Объяснение высокого уровня
Программа в основном следует этому псевдокоду:
Который злоупотребляет тем, как Hexagony пытается прочитать число, когда STDIN пуст (возвращает ноль). Большое спасибо Мартину за помощь в разработке этого подхода.
Полное объяснение
Я до сих пор не возился с Моно, чтобы запустить фантастическую эзотерическую IDE Тимви , поэтому я опирался на Мартина, чтобы предоставить мне несколько полезных симпатичных картинок!
Сначала немного о базовом контроле потока в гексагоне. Первый указатель инструкций (IP), который является единственным используемым в этой программе, начинается в верхнем левом углу гексагонального исходного кода и начинает двигаться вправо. Всякий раз, когда ИП покидает край шестиугольника, он перемещается
side_length - 1
рядами к середине шестиугольника. Поскольку эта программа использует шестиугольник с длиной стороны три, IP всегда будет перемещаться на две строки, когда это происходит. Единственное исключение - если он перемещается за пределы среднего ряда, где он условно перемещается к вершине или низу шестиугольника, в зависимости от значения текущего края памяти.Теперь немного об условностях. Только в условном Hexagony для потока управления является
>
,<
а средний край шестиугольника. Все они следуют постоянному правилу: если значение на текущем фронте памяти равно нулю или отрицательный поток управления перемещается влево, а если положителен, управление течет вправо. Квадратные скобки больше и меньше перенаправляют IP под углом шестьдесят градусов, в то время как край шестиугольника определяет, к какой строке переходит IP.Гексагония также имеет специальную модель памяти, где все данные хранятся по краям бесконечной гексагональной сетки. Эта программа использует только три ребра: одно для хранения двух, одно для текущего читаемого числа и одно для числа по модулю два. Это выглядит примерно так:
Я не собираюсь подробно объяснять, где мы находимся в памяти в каждой точке во время объяснения программы, поэтому возвращайтесь сюда, если вас смущает то, где мы находимся в памяти.
После всего этого фактическое объяснение может начаться. Сначала мы заполняем ребро «2» в памяти цифрой 2, затем выполняем no-op и перемещаем указатель памяти вправо (
2.}
).Далее мы начинаем основной цикл программы. Мы читаем первое число из STDIN, а затем нажимаем на условное выражение (
?<
). Если в STDIN не осталось чисел, это читает ноль в текущем крае памяти, поэтому мы поворачиваем налево на то@
, что завершает программу. В противном случае мы отскакиваем от зеркала, перемещаем указатель памяти назад и влево, оборачиваем вокруг шестиугольника, чтобы вычислить остаток от деления ввода на 2, а затем нажимаем на другое условие (/"%>
).Если остаток равен единице (т. Е. Число было нечетным), мы поворачиваем направо, следуя синему пути выше, начиная с повторного выполнения no-op, затем переходим к нижней части шестиугольника, умножаем текущее ребро на 10 и затем добавляем восьмой, отскочив от пары зеркал, сделайте то же самое умножение и сложение снова, получив 188 на текущем ребре, вернувшись к вершине шестиугольника, снова выполнив no-op и, наконец, завершив программу (
.8/\8.@
). Этот запутанный результат был счастливой случайностью, я изначально написал гораздо более простую логику, но заметил, что могу убрать ее в пользу запрета, который, как мне показалось, больше соответствует духу гексагонии.Если остаток был равен нулю, мы вместо этого поворачиваем налево, следуя красному пути выше. Это заставляет нас переместить указатель памяти влево, а затем распечатать значение (входное значение) в виде числа. Зеркало, с которым мы сталкиваемся, действует как no-op из-за направления, в котором мы движемся (
{/!
). Затем мы достигаем края шестиугольника, который действует условно только с одним результатом, так как входное значение, которое было до этого, уже было проверено на положительное значение, поэтому мы всегда движемся вправо (если вы представляете себя лицом в направлении IP) , Затем мы умножаем ввод на 10 и добавляем два, только чтобы изменить направление, обернуть вокруг и перезаписать новое значение на значение ascii заглавной буквы M, 77. Затем мы нажимаем на некоторые зеркала и выходим через край середины шестигранник с батутом (2<M\>$
). Так как 77 положительно, мы двигаемся вправо к нижней части шестиугольника и из-за батута пропускаем первую инструкцию (!
). Затем мы умножаем текущий край памяти на 10 и добавляем 8, получая 778. Затем мы выводим это значение mod 256 (10) в виде символа ASCII, который оказывается символом новой строки. Наконец, мы выходим из шестиугольника и возвращаемся к первому,?
который переопределяет 778 следующим входным значением.источник
Pyth,
1397 байтовКредиты @FryAmTheEggman за 2 (довольно хитрых) байта!
Объяснение:
Проверьте это здесь .
источник
G
введено два s, одно для условияs%R2G
и одно в качестве аргумента функцииP
.Желе , 5 байт
Попробуйте онлайн! или проверьте все контрольные примеры .
Как это работает
источник
Python 2,
4342 байтаФункция изменяет свой аргумент на месте .
Спасибо @xnor за умный способ сыграть в байт!
Проверьте это на Ideone .
источник
"1'"in`map(bin,x)`
в Python 2.Эд, 13
Потому что настоящие программисты используют стандартный текстовый редактор .
Принимает ввод как одно целое число в каждой строке; выходы в том же формате.
Он просто находит первое нечетное число (число, заканчивающееся нечетной цифрой) и удаляет из этой строки до конца файла.
источник
Clojure, 21 байт
Наконец, Clojure почти конкурирует! (благодаря встроенной задаче) Смотрите его на сайте https://ideone.com/BEKmez
источник
Python,
4544 байтаПроверьте это на Ideone .
источник
R, 25 байт
Или эквивалентно
источник
05AB1E,
87 байтобъяснение
Попробуйте онлайн
Предыдущее 8-байтовое решение
объяснение
Попробуйте онлайн
источник
Brainf ***, 263 байта
Я взял небольшой фрагмент отсюда
Я бы дал объяснение, но даже я понятия не имею, как это работает больше.
Ожидается ввод в виде разделенных пробелами чисел (например
2 432 1
)источник
+
и>
использовать логику?>
более эффективными, но я не понимаю их достаточно сейчасPyth, 7 байт
Попробуй это здесь!
То, что я пытался сделать в Pyke, но индекс в этом банкомате не работает
источник
Ракетка, 22 байта
Символ
λ
считается как 2 байта.Я никогда не видел, чтобы Racket использовался ранее ни в одном из кодовых ответов, которые я видел, поэтому мне пришлось сделать это хотя бы один раз!
источник
Лабиринт , 14 байт
Вход и выход представляют собой списки, разделенные переводом строки (хотя в принципе вход может использовать любой нецифровый разделитель).
Попробуйте онлайн!
Это, наверное, самая компактная программа Лабиринт, которую я когда-либо писал.
Интересно,
takewhile(odd)
что намного проще:объяснение
Обычный лабиринтный праймер:
?
в данном случае), двигаясь на восток.Основной поток через программу представляет собой один цикл по периметру:
Как это происходит, мы знаем, что вершина стека равна нулю после этого,
!
и"
поэтому гарантированно, что IP не повернет к центру.`
и%
с другой стороны, используются в качестве условных выражений, когда IP-адрес может двигаться к центру, так что@
он может завершить программу, или он может продолжать двигаться по периметру.Давайте посмотрим на код в цикле:
И тогда цикл начинается заново.
Это поднимает вопрос, почему
takewhile(odd)
так проще. Есть две причины:0
(что является четным), нам не нужна отдельная проверка EOF. В любом случае, список будет отрезан в этот момент.N % 2
есть0
(в отличие от1
), что означает, что вместо условного потока управления мы можем просто разделить другую копиюN
наN % 2
: если ввод нечетный, он просто уходит,N
и мы даже избавились отN % 2
(так что мы не t;
), но если ввод четный, это просто завершает программу с (тихой) ошибкой деления на ноль.Следовательно, другой код представляет собой простой цикл, который вообще не допускает никакого ветвления.
источник
Брахилог ,
1916 байтобъяснение
Сегодня я выучил изящный трюк (который был использован в ответе из 19 байтов):
~b.hH
он короче, чем:[H]rc.
добавление элемента в начале списка. Первый означает «Выход - это результат с дополнительным элементом в начале, а первый элемент - этоH
« » , тогда как другой является прямым «Выход - это конкатенация[[H], Result]
».источник
J, 10 байт
объяснение
источник
1{.2&|<;._2]
интересно (хотя и дольше)$
вместо{.
Python, 41 байт
Усекает
l
до индекса первого появления нечетного числа. Индекс можно найти, выполнив поиск по1
значениям по модулю2
. Чтобы избежать обнаружения нечетного числа,1
ставится конец.источник
C #, 50 байтов
источник
a=>a.TakeWhile(x=>x%2<1);
CJam , 11 байт
Спасибо @Dennis за два исправления и один байт!
Это блок кода (эквивалент функции; разрешен по умолчанию), который ожидает входной массив в стеке и оставляет выходной массив в стеке.
Попробуйте онлайн!
объяснение
источник
Сетчатка , 17 байт
Конечный перевод строки является значительным. Вход и выход - разделенные пробелами списки.
Попробуйте онлайн!
Это простая замена регулярного выражения, она соответствует первому нечетному числу (то есть числу, оканчивающемуся на нечетную цифру) и, если возможно, пробелу, предшествующему ему, а также всему, что после него, и заменяет его пустой строкой, то есть всеми элементами оттуда далее удаляются с входа.
Как указывает Лики Нун, взяв список в двоичном виде, мы можем сохранить 6 байтов, но это кажется немного обманчивым, поэтому я, вероятно, продолжу считать десятичную версию:
источник
JavaScript (Firefox 30-57), 30 байт
источник
V , 13 байт
Попробуйте онлайн!
Объяснение:
Удобно, что один и тот же код работает для проверки всех тестовых случаев одновременно.
источник
Дьялог АПЛ , 11 байт
2|
деление остатка от деления на 2~
NEGATE∧\
И-сканирование (отключается с первого 0)/⍨
выберите гдеисточник
Рубин, 25 байт
Я думаю, что проиграл ...
источник
->a{a.take_while &:even?}
или по крайней мере->a{a.take_while(&:even?)}
?Пайк, 8 байт
Исправлен переводчик, используйте другие ссылки
Использует метод Денниса, за исключением того, что моя функция split_at включает изменение - возможно, ошибка
Или с исправлением 7 байтов
Попробуй это здесь!
Или после 2-го исправления, 6 байтов
Попробуй это здесь!
Объяснение:
источник
GolfScript, 11 байт
Это полная программа GolfScript, которая считывает строковый литерал массива GolfScript (например,
[28 14 7 0]
) и распечатывает тот же массив с первым нечетным элементом и всем, что после него удалено:Попробуйте онлайн. (Также: расширенная версия с тестовым комплектом. )
Де-гольф версия с комментариями:
Это решение основано на операторе
{ },
фильтра GolfScript , который запускает содержимое блока кода для каждого элемента массива и выбирает элементы массива, для которых код в блоке возвращает истинное (то есть ненулевое) значение в вершина стека.Таким образом, например,
{1&},
выбрал бы все нечетные числа в массиве и{~1&},
выбрал бы все четные числа. Задача состоит в том, чтобы создать фильтр, который выбирает четные числа, пока не найдет первое нечетное число. , а затем вообще не выбирает числа.Решение, которое я использовал, состоит в том, чтобы заменить постоянную битовую маску
1
(используемую для извлечения младшего бита каждого входного числа) переменной в стеке, которая хранит результат (0 или 1) предыдущей итерации цикла фильтра (и инициализируется как 1 перед циклом). Таким образом, как только фильтр возвращает 0 один раз, битовая маска также устанавливается в 0, предотвращая когда-либо фильтр снова возвращать 1.источник
Далее 114 байтов
У Forth действительно нет списков. Параметры должны быть помещены в стек в обратном порядке, как это типично для Forth. Результат будет оставлен в стеке в том же порядке. По некоторым причинам это не работает на Ideone, но работает на repl. Новая строка требуется, чтобы устранить какую-то двусмысленность?
Попробуйте онлайн
Ungolfed, с комментариями:
Эта программа (моя предыдущая попытка) печатает результаты, пока не достигнет нечетного числа. Все остальное (не взятое) останется в стеке.
Сбой, если только целые числа
источник
Befunge, 35 байт
Этот код обрабатывает числа от 0 до 65535
Формат ввода:
Вот версия, которая отображает значения в конце процесса:
Вы можете проверить код здесь , но вам нужно будет добавить завершающую строку с конечными пробелами, так как это интерпретация указывает:
Я не знаю, является ли это приемлемым, так как я не учел этот трейлинг в подсчете байтов
nb: кажется, что, поскольку я храню число в коде, интерпретатор не позволит этой программе работать дважды в правильном путь. Вам придется перезагрузить его.
Как это работает: переводчик следует за стрелками и пропускает инструкцию при пересечении '#'
Серые точки проверены, а красная линия удаляет ненужные переменные из стека
Используя здесь в приведенном выше интерпретаторе, сохраненные значения отображаются в коде, используя их представления (я не знаю формат). Да, Befunge - довольно рефлексивный язык
источник