No outro dia, nossa equipe foi para uma sala de fuga. Um dos quebra-cabeças envolvia uma placa de seis interruptores mecânicos, onde era necessário encontrar a combinação correta de ligar e desligar para destravar uma caixa, mais ou menos assim:
-v-v-v-
-v-v-v-
Sendo desenvolvedores, decidimos que seria mais eficiente tentar todas as combinações 2 ^ 6 = 64 do que realmente resolver o enigma. Então, designamos um cara pobre para fazer uma contagem binária:
-v-v-v-
-v-v-v-
-v-v-v-
-v-v-^-
-v-v-v-
-v-^-v-
-v-v-v-
-v-^-^-
e assim por diante.
O desafio
Escreva um programa que, considerando todos os interruptores na posição desligado, como uma string formatada como acima, gere todas as combinações de ligado e desligado em qualquer ordem.
Você pode escrever um programa completo ou uma função. Portanto, seu programa pode receber entradas através de stdin, um arquivo ou como um argumento de cadeia única e retornar ou imprimir a saída. Se retornado, a saída pode estar em uma lista / array / etc. em vez de uma única sequência. Se a saída for uma única sequência, as placas deverão ser separadas por novas linhas (novas linhas finais são permitidas).
As seqüências de entrada corresponderão ao regex r'((-v)+-)(\n(-v)+-)*'
e representarão uma placa com todos os interruptores desativados. Isso significa que não há zero caso, e os comutadores estão alinhados à esquerda. Cada linha pode não ter o mesmo número de opções.
Cada placa de saída deve ter exatamente o mesmo formato da entrada, exceto que os vs podem ser substituídos por ^ 's conforme necessário. As placas de saída podem ser separadas por qualquer número de novas linhas.
Como o tempo de execução é naturalmente O (2 ^ n) no número de comutadores, seu código não será testado em mais de 10 comutadores em qualquer organização.
Este é o código-golfe, pelo que o código mais curto em número de bytes vence.
Amostras de entradas e saídas
Entrada:
-v-
Saída possível:
-v-
-^-
Entrada:
-v-
-v-
Saída possível:
-^-
-^-
-^-
-v-
-v-
-^-
-v-
-v-
Como é extremamente tedioso verificar sua resposta para um número maior de opções, aqui está um script Python como uma ferramenta de verificação de integridade. (Incluí um trecho comentado no momento para gerar a saída esperada de um determinado arquivo de entrada, caso você queira mais casos de teste.) É um pouco menos flexível em termos de entrada e saída do que a especificação, infelizmente; coloque a string de entrada em um arquivo chamado 'input' e a saída separada por nova linha (desculpe, sem formatação de lista) em um arquivo chamado 'output' no mesmo diretório e execute python3 sanitycheck.py
.
fonte
Respostas:
Haskell ,
25242317 bytesExperimente online!
-1 byte graças a @ H.PWiz
-1 byte graças a @nimi
Retorna uma lista de strings. O TIO possui 2 bytes extras para a declaração da função - vi outras pessoas desativando-as quando escrevem a função sem pontos, então estou fazendo o mesmo, a menos que seja dito o contrário.
Resposta anterior (25 bytes)
As explicações são todas para a resposta anterior, que funciona praticamente da mesma maneira, exceto que eu descrevi a definição de
g
. A forma comog
funciona agora é usando comparação lexical de substituir^v
porv
e manter tudo o mais o mesmo.Curiosamente, isso funciona para quadros de distribuição arbitrários:
Explicação (Breve)
Explicação (longa)
mapM
é uma função bastante assustadora para aqueles que não estão familiarizados com Haskell. Mas não é difícil de entender neste contexto. Ao fazê-lo agir sobreString
s (que em Haskell são listas de caracteres), eu o especializei em sua definição para listas. Portanto, nesse contexto, sua assinatura de tipo éNa verdade, ele é ainda mais especializado em meu uso -
a
eb
ambosChar
- para que possamos ver a assinatura do tipo comoVamos analisar rapidamente o que
g
faz antes de explicar comomapM
funciona.g
usa a correspondência de padrões para converterChar 'v'
a string"v^"
; todo o resto é convertido em uma string singleton (lembre-se, strings são apenas listas deChar
s, para que possamos colocarx
uma lista singleton). Testando no REPL, descobrimos que este é o casoObserve que
g
tem o tipo certo para ser um argumentomapM
(sem surpresa!).Vamos explorar como
mapM
funciona, fornecendo-og
e o argumentocomo entrada.
mapM
primeiros mapasg
sobreString
e, comog
converteChar
s paraStrings
, isso nos fornece uma lista deStrings
Embora este seja o tipo de saída correto,
mapM
faz um pouco mais. Você pode pensar nisso como formando todos osString
s que você poderia criar nesta lista se tivesse que escolher um único caractere para cada um delesString
(em ordem).Portanto, para o primeiro elemento, você não tem outra escolha senão escolher o
Char '-'
. Para o segundo elemento, você pode escolher entre'v'
e'^'
assim por diante.É aproximadamente equivalente a este código python:
Exceto que desde separa Haskell entre
Char
s eString
s, quando ele coloca osChar
s em uma lista, ele não precisajoin
deles.Portanto, a saída final é
como desejado.
fonte
mapM
trabalhado para esse desafio, no começo eu o tinha formulado,sequence . map g
mas isso pode ser expresso de forma compactamapM id . map g
e então eu vi que podiamapM g
=='v'
por>'-'
Perl 6 , 32 bytes
Experimente online!
.comb
divide a string em caracteres.».&{...}
mapeia os caracteres de acordo com a função entre os chavetas.$_, ('^' if /v/)
produz uma lista de alternativas para cada caractere. Sóv
tem uma alternativa:^
.[X~]
reduz essa lista com o operador de produto cruzado de concatenação de cadeiasX~
.fonte
Geléia , 7 bytes
Experimente online!
Saída é uma lista de seqüências de caracteres Jelly.
Explicação:
fonte
Perl 5 , 29 bytes
Experimente online!
Minha primeira submissão!
Normalmente, os golfistas do Perl 5 enviam programas em vez de funções para evitar a necessidade de incluir
sub{}
no mínimo. Mas eles têm que adicionarsay
,say␠
,say for
ousay for␠
em troca.Seguindo a sub-abordagem, eu poderia reduzir
para
A explicação é bastante simples. O Perl 5 possui um
glob
operador interno que aceita um padrão glob do tipo shell que pode ser usado para gerar listas de nomes de arquivos (por exemplofoo*.txt
) ou lista de strings (por exemplo{a,b,c}
). O problema é que a nova linha precisa ser escapada, o que eu fiz usandoquotemeta
(as\Q
).fonte
K (ngn / k) ,
2725 bytesExperimente online!
"^"/"v"\
substitua"v"
por"^"
x,'
zip com os caracteres originais(,/,/:\:)/
produto cartesiano?
uniqfonte
APL (Dyalog Classic) ,
21 1715 bytesExperimente online!
semelhante à minha solução k
retorna uma matriz n-dimensional de cadeias (n = número de opções)
de forma mais fácil de explicar:
⊃(∘.,⌿ ⊢ ∪¨ 'v'⎕r'^')
'v'⎕r'^'
substituav
s por^
s⊢ ∪¨
... uniões com cada um dos personagens originais. é um vetor de cadeias de comprimento 1 ou 2∘.,⌿
redução de produto cartesiano⊃
divulgarpara chegar à versão completa, seguimos o padrão
f⌿ A g¨ B
->A f.g B
:∘.,⌿ ⊢ ∪¨ 'v'⎕r'^'
->⊢ ∘.,.∪ 'v'⎕r'^'
como efeito colateral, os parênteses não são mais necessários
fonte
J , 42 bytes
Experimente online!
explicação
Vamos dar
como nosso exemplo de entrada.
('v^' {~ 2 #:@i.@^ 1 #. e.&'v')
cria todos os combos possíveis apenas dos comutadores, ignorando o formato de entrada. para o nosso exemplo, ele produz:1 #. e.&'v'
conta os números dev
s na entrada.2 #:@i.@^
aumenta 2 para esse poder, produz os números inteiros de 0 para esse númeroi.
e os converte em binários#:
'v^' {~
muda para dígitos binários parav
e^
]`('v' I.@e.~ [)`[}"1
altera a entrada original, produzindo uma cópia para cada linha do resultado descrito na etapa anterior (ou seja, todos os possíveisv
/^
combos). Em cada cópia, av
entrada original é substituída por uma sequência possível dev
/^
.fonte
Java,
202197189191 bytesSim, é uma linguagem comparativamente detalhada, mas é isso que considero como golfe clássico:
Eu pensei que uma maneira "simples" de lidar com as quebras de linha necessárias para obter o layout adequado era realmente reutilizar a matriz de caracteres de entrada original e preenchê-la apenas com
'v'
s e'^'
s nas posições apropriadas.Atualizações:
Descobriu-se que não armazenar as posições permite abandonar as
int
declarações de variáveis e array (ao custo de verificar cada posição do array se ele contém umv
ou^
em movimento), economizando 5 bytes.Outros 8 bytes salvos ao calcular o limite superior
(1<<numberOfSwitches)
superior de forma mais compacta.De acordo com a regra mencionada no comentário, a declaração da função deve ser contada, então agora é uma lambda ...
fonte
String generate(String s) {...}
) na sua contagem de bytes. Aqui está uma versão fixa / lambda para 191 bytes . Eu fiz um pouco de golfe para raspar 3 bytes{ function body }
deveria ser relevante, porque não importa se você o coloca em uma função que éstatic
ou não e, é claro, se a declaração conta para a pontuação, pode-se convertê-la em uma expressão lambda. Mas é isso que é feito agora, obrigado por apontar isso.d=94
). 2. Inicializei
quando você a declarar. 3. Use emi++<m
vez do incremento separado (é necessário modificar o conteúdo do loop em um único local, mas isso não agrega custo). 4. Você consegue se safar(i&1<<j++)>0
? 5. Acho que você não precisa do loop{}
internofor
. 6. Você pode substituira[k]==d||a[k]==u
pora[k]>45
, eu acho. 7. Vá comj=k=0
. Tudo isso deve remover 19 bytes.{}
são necessárias, mas posso dar uma outra olhada. Noa[k]>45
entanto, pode ser um truque interessante. É certo que eu escrevi isso apenas para perder algum tempo esperando o início de uma reunião (daí o nome da classe - isso foi intencional ;-)), mas talvez eu deva dar outra olhada - obrigado em qualquer caso!J ,
41 4024 bytesExperimente online!
fonte
{
. embora eu ache que[:>@,@{<@(,'^'$~'v'=])"0
seria um pouco mais justo, já que "Cada placa de saída deve ter exatamente o mesmo formato da entrada" e a entrada não está na caixa.Python 2 , 87 bytes
Experimente online!
Uma abordagem não regular.
fonte
C (gcc) ,
75 7470 bytes-5 byte graças a @ceilingcat
Experimente online!
requer que os
s
pontos de memória sejam graváveisfonte
Python 3.8 (pré-lançamento) ,
129 117 116 110106 bytes-10 bytes graças a @Chas Brown
Experimente online!
fonte
C (gcc) , 102 bytes
Experimente online!
fonte
K4 , 44 bytes
Solução:
Exemplos:
Explicação:
Substituição no local de
"^"
. Determine o número de combinações de comutadores (por exemplo, 2 ^ n), conte em binário, substitua comutadores ...fonte
R , 116 bytes
Experimente online!
Função retornando um vetor de placas separadas por nova linha
fonte
"[<-"
!JavaScript, 88 bytes
Experimente online!
fonte
n>>=1
->n/=2
Retina 0.8.2 , 29 bytes
Experimente online! Explicação:
Altere as novas linhas em
;
s ev
s em#
marcadores.Substitua os
#
um de cada vez, da esquerda para a direita.Mude cada linha em duas linhas, uma com a
#
substituída por av
, uma com a substituída por a^
.Mude as
;
costas para novas linhas e espace os resultados.fonte
Perl 5
-0
, 51 bytesExperimente online!
fonte
-n
teria evitado a necessidade de$_=<>;
JavaScript (Node.js) ,
80 7368 bytesExperimente online!
fonte
Python 3 - construção, 203 bytes
Experimente online!
Primeira tentativa, não muito pequena, mas funciona. Não há substituição de string elegante no Python ...
O primeiro loop constrói um mapeamento de linhas para índices de bits, ou seja, para cada linha, o índice do primeiro bit em um contador de bits é armazenado. Isso é usado para indexar o contador de bits no próximo loop.
O segundo loop executa um contador binário, extrai os bits para cada linha e iteração e os une. Depois de juntar tudo, ele é convertido de volta para o formato do mapa de comutador, usando a substituição de string.
Eu acho que existe uma maneira mais elegante de reutilizar a string de entrada em vez de reconstruí-la repetidamente.
Edit: inspirado na resposta do Python 3.8 , aqui está uma versão de substituição muito mais curta
Python 3 - substituir, 123 bytes
Experimente online!
fonte
Rubi , 64 bytes
Em Ruby,
i[j]
retorna oj
th bit dai
partida do bit menos significativo, ou seja, é equivalente a(i>>j)&1
.Experimente online!
fonte
Carvão , 28 bytes
Experimente online! Link é a versão detalhada do código. Explicação:
fonte
PHP , 93 bytes
Experimente online!
Programa autônomo, entrada via linha de comando.
Loop o número de permutações possíveis da sequência de entrada com base no número de
v
's. Enquanto conta em binário, substitua cada binário1
por a^
e cada binário0
por av
na sequência de entrada.fonte