На днях наша команда отправилась в комнату побега. Одна из головоломок была связана с платой из шести механических переключателей, где вам нужно было найти правильную комбинацию включения и выключения, чтобы разблокировать коробку, примерно так:
-v-v-v-
-v-v-v-
Будучи разработчиками, мы решили, что было бы эффективнее попробовать каждую из 2 ^ 6 = 64 комбинаций, чем решить головоломку. Итак, мы назначили какого-то бедного парня для двоичного подсчета:
-v-v-v-
-v-v-v-
-v-v-v-
-v-v-^-
-v-v-v-
-v-^-v-
-v-v-v-
-v-^-^-
и так далее.
Задача
Напишите программу, которая, учитывая все переключатели в выключенном положении в виде строки, как указано выше, генерирует все комбинации включения и выключения в любом порядке.
Вы можете написать либо полную программу, либо функцию. Таким образом, ваша программа может принимать входные данные через stdin, файл или в виде строкового аргумента, а также возвращать или распечатывать выходные данные. Если возвращено, вывод может быть в списке / массиве и т. Д. а не одна строка. Если выходные данные представляют собой одну строку, доски должны быть разделены символами новой строки (конечные символы новой строки разрешены).
Входные строки будут соответствовать регулярному выражению r'((-v)+-)(\n(-v)+-)*'
и представляют одну плату со всеми выключенными выключателями. Это означает отсутствие нуля, и переключатели выровнены по левому краю. Каждая строка может не иметь одинакового количества переключателей.
Каждая плата вывода должна быть точно такого же формата, что и входные данные, за исключением того, что буквы v могут быть заменены символами ^ при необходимости. Таблицы вывода могут быть разделены любым количеством новых строк.
Поскольку время выполнения, естественно, равно O (2 ^ n) по количеству переключателей, ваш код не будет тестироваться на более чем 10 переключателях в любом порядке.
Это код-гольф, поэтому выигрывает самый короткий код в количестве байтов.
Образцы входов и выходов
Входные данные:
-v-
Возможный вывод:
-v-
-^-
Входные данные:
-v-
-v-
Возможный вывод:
-^-
-^-
-^-
-v-
-v-
-^-
-v-
-v-
Поскольку проверять ваш ответ на большее количество переключателей крайне утомительно, вот скрипт Python как инструмент проверки работоспособности. (Я включил закомментированный в настоящее время фрагмент кода для генерации ожидаемого вывода из заданного входного файла на случай, если вам нужно больше тестовых случаев.) К сожалению, он немного менее гибок в плане ввода и вывода, чем спецификация; поместите входную строку в файл с именем 'input', а вывод с разделителями новой строки (извините, форматирование списка отсутствует) в файл с именем 'output' в том же каталоге и запустите python3 sanitycheck.py
.
источник
Ответы:
Haskell ,
25242317 байтПопробуйте онлайн!
-1 байт благодаря @ H.PWiz
-1 байт благодаря @nimi
Возвращает список строк. У TIO есть 2 дополнительных байта для объявления функции - я видел, как другие люди оставляли это, когда они пишут функцию pointfree, поэтому я делаю то же самое, если не указано иное.
Предыдущий ответ (25 байт)
Все объяснения относятся к предыдущему ответу, который работает примерно так же, за исключением того, что я включил определение
g
. Способg
работает теперь с помощью лексического сравнения заменить^v
наv
и держать все остальное то же самое.Интересно, что это работает для произвольных коммутаторов:
Объяснение (короткое)
Объяснение (Длинное)
mapM
это довольно страшная функция для тех, кто не знаком с Haskell. Но это не сложно понять в этом контексте. Заставив его действовать наString
s (который в Haskell - списки символов), я специализировал его для определения списков. Таким образом, в этом контексте его тип подписиЭто на самом деле еще более специализировано в моем использовании -
a
иb
обаChar
- так что мы можем увидеть сигнатуру типа какДавайте быстро посмотрим, что
g
делает, прежде чем объяснять, какmapM
работает.g
использует сопоставление с шаблоном для преобразованияChar 'v'
в строку"v^"
; все остальное преобразуется в одноэлементную строку (помните, что строки - это просто спискиChar
s, поэтому мы можем поместить ихx
в одноэлементный список). Тестируя на REPL, мы находим, что это такОбратите внимание, что
g
имеет правильный тип, чтобы быть аргументомmapM
(неудивительно!).Мы рассмотрим, как это
mapM
работает, предоставив егоg
и аргументв качестве ввода.
mapM
первые картыg
надString
, и посколькуg
преобразуетChar
s вStrings
, это дает нам списокStrings
Хотя это правильный тип вывода,
mapM
делает немного больше. Вы можете думать об этом как о формировании всегоString
s, которые вы можете создать из этого списка, если вам нужно было выбрать один символ из каждогоString
в нем (по порядку).Поэтому для первого элемента у вас нет другого выбора, кроме как выбрать
Char '-'
. Для второго элемента вы можете выбрать между'v'
и'^'
так далее, и так далее.Это примерно эквивалентно этому коду Python:
За исключением того, что, поскольку Haskell разделяет
Char
s иString
s, когда он помещаетChar
s в список, он им не нуженjoin
.Итоговый результат
по желанию.
источник
mapM
сработал этот вызов, сначала я сформулировал его так,sequence . map g
но это можно выразить компактно, аmapM id . map g
затем я увидел, что могу простоmapM g
=='v'
на>'-'
Perl 6 , 32 байта
Попробуйте онлайн!
.comb
разбивает строку на символы.».&{...}
сопоставляет символы в соответствии с функцией между фигурными скобками.$_, ('^' if /v/)
создает список альтернатив для каждого символа. Толькоv
есть альтернатива^
.[X~]
сокращает этот список с помощью оператора перекрестных произведений конкатенации строкX~
.источник
Желе , 7 байт
Попробуйте онлайн!
Выводит список строк Jelly.
Объяснение:
источник
Perl 5 , 29 байт
Попробуйте онлайн!
Моя первая подача!
Как правило, игроки в Perl 5 представляют программы вместо функций, чтобы избежать необходимости включать их
sub{}
как минимум. Но они должны добавитьsay
,say␠
,say for
илиsay for␠
в обмен.Пройдя суб подход, я мог бы сократить
в
Объяснение довольно простое. В Perl 5 есть встроенный
glob
оператор, который принимает шаблон глобуса в виде оболочки, который можно использовать для создания списков имен файлов (напримерfoo*.txt
) или списка строк (например{a,b,c}
). Уловка в том, что нужно экранировать символ новой строки, что я и сделалquotemeta
(as\Q
).источник
K (нгн / к) ,
2725 байтПопробуйте онлайн!
"^"/"v"\
заменить"v"
на"^"
x,'
почтовый индекс с оригинальными символами(,/,/:\:)/
декартово произведение над?
уникисточник
APL (Dyalog Classic) ,
21 1715 байтПопробуйте онлайн!
похоже на мое решение к
возвращает n-мерный массив строк (n = количество переключателей)
в более легкой для объяснения форме:
⊃(∘.,⌿ ⊢ ∪¨ 'v'⎕r'^')
'v'⎕r'^'
заменитьv
s на^
s⊢ ∪¨
... союзы с каждым из оригинальных персонажей. это вектор строк длиной 1 или 2∘.,⌿
сокращение декартовых произведений⊃
раскрыватьчтобы добраться до полностью гольфовой версии, мы следуем схеме
f⌿ A g¨ B
->A f.g B
:∘.,⌿ ⊢ ∪¨ 'v'⎕r'^'
->⊢ ∘.,.∪ 'v'⎕r'^'
в качестве побочного эффекта скобки больше не нужны
источник
J , 42 байта
Попробуйте онлайн!
объяснение
Давай возьмем
как наш пример ввода.
('v^' {~ 2 #:@i.@^ 1 #. e.&'v')
создает все возможные комбинации только переключателей, игнорируя формат ввода. для нашего примера это производит:1 #. e.&'v'
считает числаv
s на входе.2 #:@i.@^
поднимает 2 до этой степени, производит целые числа от 0 до этого числаi.
и преобразует их в двоичные#:
'v^' {~
изменения в двоичные цифрыv
и^
]`('v' I.@e.~ [)`[}"1
вносит изменения в исходный входной, производя одну копию для каждой строки результата описано в предыдущем шаге (то есть, все возможныеv
/^
комбо). В каждом экземпляреv
исходные данные заменяются одной возможной последовательностьюv
/^
.источник
Ява,
202197189191 байтДа, это сравнительно многословный язык, но это то, что я считаю классическим гольфом:
Я подумал, что «простой» способ справиться с разрывами строк, которые необходимы для правильной разметки, состоит в том, чтобы фактически повторно использовать исходный входной массив символов и заполнять его только
'v'
s и'^'
s в соответствующих позициях.Обновления:
Оказалось, что отсутствие сохранения позиций позволяет исключить
int
объявления переменных и массива (за счет проверки каждой позиции массива, независимо от того, содержит онv
или^
на лету), экономя 5 байтов.Еще 8 байтов сохраняются путем вычисления верхнего предела
(1<<numberOfSwitches)
более компактно.Согласно правилу, упомянутому в комментарии, объявление функции должно учитываться, так что теперь это лямбда-выражение ...
источник
String generate(String s) {...}
) в ваш счетчик байтов. Вот фиксированная / лямбда-версия для 191 байта . Я немного поиграл в гольф, чтобы сбрить 3 байта{ function body }
должно быть актуальным, потому что не имеет значения, помещаете ли вы его в функцию, которая естьstatic
или нет, и, конечно, если объявление засчитывается в счет, можно преобразовать его в лямбда-выражение. Но это то, что сделано сейчас, спасибо за указание на это.d=94
). 2. Инициализируйте,i
когда вы объявите это. 3. Используйтеi++<m
вместо отдельного приращения (необходимо изменить содержимое цикла в одном месте, но это не добавляет затрат). 4. Можете ли вы сойти с рук(i&1<<j++)>0
? 5. Я не думаю, что вам нужно{}
для внутреннегоfor
цикла. 6. Вы можете заменитьa[k]==d||a[k]==u
наa[k]>45
, я думаю. 7. Иди сj=k=0
. Все это должно удалить 19 байт.{}
них необходимы, но я могу взглянуть по-другому. Однако, этоa[k]>45
может быть изящный трюк. По общему признанию, я только написал это, чтобы потратить некоторое время на ожидание начала собрания (отсюда и название класса - это было намеренно ;-)), но, возможно, я посмотрю по-другому - спасибо в любом случае!J,
41 4024 bytesTry it online!
источник
{
. although i think[:>@,@{<@(,'^'$~'v'=])"0
would be slightly more fair since "Each output board should be of the exact same format as the input" and the input isn't boxed.Python 2, 87 bytes
Try it online!
A non-regex approach.
источник
C (gcc),
75 7470 bytes-5 byte thanks to @ceilingcat
Try it online!
requires the memory
s
points to to be writableисточник
Python 3.8 (pre-release),
129 117 116 110106 bytes-10 bytes thanks to @Chas Brown
Try it online!
источник
C (GCC) , 102 байта
Попробуйте онлайн!
источник
K4 , 44 байта
Решение:
Примеры:
Объяснение:
Замена на месте
"^"
. Определить количество комбинаций переключателей (например, 2 ^ n), сосчитать в двоичном коде, заменить переключатели ...источник
R , 116 байт
Попробуйте онлайн!
Функция, возвращающая вектор разделенных досками новой строки
источник
"[<-"
!JavaScript, 88 bytes
Try it online!
источник
n>>=1
->n/=2
Retina 0.8.2, 29 bytes
Try it online! Explanation:
Change the newlines into
;
s and thev
s into#
markers.Replace the
#
s one at a time from left to right.Change each line into two lines, one with the
#
replaced with av
, one with it replaced with a^
.Change the
;
s back into newlines and space the results apart.источник
Perl 5
-0
, 51 bytesTry it online!
источник
-n
would have avoided the need for$_=<>;
JavaScript (Node.js),
80 7368 bytesTry it online!
источник
Python 3 - construct, 203 bytes
Try it online!
First try, not very small but works. There is no elegant string replacement in Python...
The First loop builts a mapping of lines to bit indices, i.e. for each line, the index of the first bit in a bit counter is stored. This is used for indexing the bit counter in the next loop.
The Second loop runs a binary counter, extracts the bits for each line and iteration and joins them. After joining everything together, it is translated back to the switch map format, using string replacement.
I guess, there is a more elegant way by reusing the input string instead of rebuilding it over and over again.
Edit: inspired by the Python 3.8 answer, here is a much shorter replacing version
Python 3 - replace, 123 bytes
Try it online!
источник
Ruby, 64 bytes
Returns an array. Gets numbers from1 to 2v (where v is the number of "v" in the input) and flips switches based on the v least significant bits. This allows us to save a byte over iterating from 0 to 2v−1 , because the v least significant bits in 2v are all zero.
In Ruby,
i[j]
returns thej
th bit ofi
starting from the least significant bit, aka it is equivalent to(i>>j)&1
.Try it online!
источник
Charcoal, 28 bytes
Try it online! Link is to verbose version of code. Explanation:
источник
PHP, 93 bytes
Try it online!
Standalone program, input via command line.
Loop the number of possible permutations of the input string based on the number of
v
's. While counting up in binary, replace each binary1
with a^
and each binary0
with av
in the input string.источник