Simular a rotação de uma placa

14

Introdução

Você está jogando um jogo de correspondência, no qual as moedas são inseridas no topo e caem no fundo (na moeda de cima) devido à gravidade.

Então, é isso

O <- inserting this coin

OO O
OOOOO

vai se tornar isso

O
OO O
OOOOO

Agora imagine alguém girando o quadro no sentido horário. O seguinte acontecerá:

1. A placa é girada

OOO
OO
O
OO
O

2. Moedas caem devido à gravidade

O
O
OO
OO
OOO

Sua tarefa

Sua tarefa é simular a rotação do quadro escrevendo um programa ou uma função. Por uma questão de simplicidade, estamos lidando apenas com um tipo de moeda (não é um jogo de correspondência muito emocionante, é…). Você pode assumir que a gravidade é aplicada somente depois que a rotação estiver concluída. A placa é girada no sentido horário.

Entrada

A entrada será uma string, que contém 3 tipos de caracteres:

  • O (capital o) OR 0 (zero) - uma moeda (você decide qual delas sua solução suporta)
  • (espaço) - um campo vazio
  • \ n (nova linha) - fim de linha

A entrada representa o estado do quadro. Você pode assumir que a entrada está bem formada e contém um estado válido do tabuleiro (nenhuma moeda está flutuando). A entrada pode ser um parâmetro de função ou pode ser lida a partir da entrada padrão ou de um arquivo.

Resultado

A saída é o novo estado da placa após a rotação. A saída contém os mesmos 3 tipos de caracteres que a entrada. A saída pode ser retornada da sua função ou pode ser gravada na saída padrão ou em um arquivo.

Amostra

Entrada1:

O
OO O
OOOOO

Saída1:

O
O
OO
OO
OOO

Entrada2:

O O
O O

Saída2:

OO
OO

Você pode usar qualquer idioma e a biblioteca padrão do idioma escolhido. O programa mais curto em bytes vence.

David Frank
fonte
As linhas mais curtas são preenchidas com espaços à direita?
Ventero
Se você precisar, então sim.
David Frank
Quais são os requisitos para o tamanho da placa? Posso escolher um tamanho máximo razoável ou o aplicativo / função precisa funcionar para todos os tamanhos possíveis?
Fors
2
Se a gravidade é aplicada após a rotação, como a Entrada2 se torna a Saída2? Eu teria pensado que derrubaria as moedas de cima, mas não horizontalmente?
Matt
2
@ Matt Observe que não há linhas vazias na Entrada2 nem na Saída2 (o SE exibe margem entre as linhas).
David Frank

Respostas:

16

GolfScript, 14 12 caracteres

' '-n%zip$n*

A entrada deve ser fornecida no STDIN; o caractere para moedas pode ser qualquer caractere que não seja um espaço em branco. Tente aqui . Agradecemos a Peter por apontar uma redução de dois caracteres.

Howard
fonte
Oh, o que eu não daria por um transposeem Ruby que pode lidar com matrizes com diferentes comprimentos ...
Ventero
@Ventero Na maioria das vezes eu uso esta versão hacky: ([nil]*a.map(&:size).max).zip(*a). Não é bom para jogar golfe.
26414 Howard Howard
Você pode salvar 2 caracteres: como as linhas mais longas sempre terminam na parte inferior, você pode substituir -1%por $.
Peter Taylor
@ PeterTaylor Você está certo - podemos salvar em caracteres. Obrigado.
26414 Howard Howard
1
@ PeterTaylor Bem, eu incluí um alias de um caractere para " ".
Aditsu
6

Javascript (E6) 103

Primeira tentativa, apenas operações de matriz. Cada linha na sequência de entrada precisa ser preenchida.
Bastante prolixo.

R=t=>(x=t.split('\n').reverse().map(x=>[...x].sort()),x.map((c,i)=>x.map(r=>r[i]).join('')).join('\n'))

Pseudo-código

  1. string -> matriz de linhas
  2. matriz reversa para cima / para baixo
  3. cada linha -> matriz de caracteres
  4. classifique cada linha (moedas 'caem' para a direita)
  5. transpor
  6. cada matriz de caracteres em uma linha -> uma string
  7. matriz de junção -> sequência única
edc65
fonte
Oh uau, a classificação é inteligente (+1)! Se importa se eu roubá-lo?
26/06
Eu nunca vi a sintaxe [...x]antes. Como isso é chamado?
ComFreek
2
@ edc65 Você quebrou seu próprio link com colchetes. Aqui está o link correto
Chris Cirefice
6

Ruby 2.0, 59 caracteres

puts$<.map(&:chars).reverse.transpose.sort[1,50].map &:join

Entrada via stdin, assume que todas as linhas têm o mesmo comprimento. Provavelmente é muito mais tempo do que o necessário. Mas pelo menos é legível ...

Ventero
fonte
Eu acho que você pode usar em seu $<.maplugar.
Howard
@ Howard Essa é uma coisa que eu sempre esqueço. Obrigado!
Ventero 26/06
1
o que [1,50] está fazendo lá?
Não que Charles,
1
@Charles Pula a primeira linha, que contém todas as novas linhas da entrada. David mencionou em um comentário que 50x50 é o tamanho máximo possível; portanto, em vez de selecionar tudo, exceto a primeira linha ( 1..-1), apenas seleciono 50 linhas começando com a segunda ( 1,50).
Ventero
@Ventero entendeu. legal. obrigado!
Não que Charles,
3

J - 49 31 24 bytes

Acho que pode haver rotações desnecessárias, mas, caso contrário, funciona bem. É uma função que recebe a entrada conforme especificado, sendo as moedas O. Nenhum espaço em branco à direita é necessário na entrada.

Nova versão, inspirada na resposta Javascript de edc65 :

f=:[:|."1@|:[:/:~"1,;._2

Explicação:

f=:[:|."1@|:[:/:~"1,;._2
                   ,;._2 Split the string at every fret, which is the last character in the string (newline).
              /:~"1      Sort every row separately.
     |."1@|:             Rotate the array clockwise.

Versão antiga:

f=:[:|:((#~=&' '),=&'O'#])"1@|:@(|."1@|:)@(,;._2)

Explicação:

f=:[:|:((#~=&' '),=&'O'#])"1@|:@(|."1@|:)@(,;._2)
                                          (,;._2) Split the string at every fret, which is the last character in the string (newline).
                                (|."1@|:)@        Rotate the array clockwise.
                             |:@                  Reverse the axes (columns become rows and vice-versa).
       ((#~=&' '),=&'O'#])"1                      Function that applies the "gravity"
                          "1                       Apply to every row separately:
                  =&'O'#]                           Get the O's in the row.
       (#~=&' ')                                    Get the spaces in the row.
                ,                                   Join them, spaces come first.
  [:|:                                            Reverse axes again.

Exemplos (observe que cadeias de 0 : 0linhas múltiplas começam com e terminam com um colchete):

   f 0 : 0
O
OO O
OOOOO
) NB. output starts now
O  
O  
OO 
OO 
OOO
   f 0 : 0
O O
O O
) NB. Output starts now.

OO
OO
seequ
fonte
Se você puder, tipo antes de girar
edc65
@ edc65 Você é um homem inteligente.
seequ
2

Haskell - 86

Apenas aprendendo, então tenho certeza que isso pode ser melhorado.

import Data.List
c=putStr.unlines.filter(/="").sort.map(filter(/=' ')).transpose.lines

Entrada de amostra:

let a = "O    \nOO O \nOOOOO"
let b = " O O \n O O "
c a
c b

Saída de amostra:

O
O
OO
OO
OOO

OO
OO
OI
fonte
2

Python 2 (69) (79)

for c in sorted(zip(*raw_input().split("\\n"))):print''.join(c[::-1])

Aceita entrada preenchida com espaços para que todas as linhas tenham o mesmo comprimento. O splitcria uma arrat de cada linha. O ziptranspõe eficazmente a matriz. Em seguida, sortedclassifica as tuplas em ordem lexicográfica, fazendo com que todas as moedas caiam no fundo. Finalmente, imprimimos cada linha, transformando-a novamente em uma string, embora devamos revertê-la primeiro. Fazer print'O'*c.count('O')é equivalente e usa o mesmo número de caracteres.

Exemplo de execução:

>> O    \nOO O \nOOOOO
O
O
OO
OO
OOO
xnor
fonte
1

C, 167 119 bytes

Esta versão mais curta é (infelizmente?) Muito mais clara que a original também.

m;j;b[99];r;main(){while(j=getchar()+1)j-11?m+=j-33&&++b[r]>m:++r;for(j=r;m+1;putchar(j--?m<b[j]?79:32:(j=r,m--,10)));}
j_random_hacker
fonte
0

Raquete: 130

(let l((a'()))(let((b(sort(string->list(read-line))char<?)))(if
(null? b)(apply map(λ x(map display x)(newline))a)(l(cons b a)))))

Requer que você preencha com espaços para que as linhas sejam iguais.

Sylwester
fonte
0

C # - 209 174 bytes

Certo, eu tenho que tentar este código de golfe em algum momento, eu acho. Criou uma função (r) que gira o quadro e o imprime. Acho que estou trapaceando um pouco quando estou imprimindo minha matriz de caracteres, mas se você não consegue entender por que não deveria ficar bravo :)

Obrigado ao ProgramFOX pelas dicas :)

void r(string s){int x=s.IndexOf('\n'),j,i=-1,k,z=x+1;var y=new char[x*x+x];for(;++i<x;y[z*(i+1)-1]='\n')for(k=j=x;j>0;)if(s[i*z+--j]=='0')y[k--*z-i-2]='0';Console.Write(y);}

Enganação

new char[x*x+x]preenche a matriz com '\0'e não' '

WozzeC
fonte
1
Remover as novas linhas e remover o espaço entre char[]e yreduzirá a contagem de caracteres para 192 caracteres. Além disso, não é realmente necessário fornecer a palavra-chave staticao postar uma resposta aqui. Removê-lo reduzirá a contagem de caracteres para 185 caracteres.
precisa
Também pude remover 'ref', que foi esquecido desde uma tentativa anterior.
WozzeC