> <> Fora da água

20

O peixe amado que nada através do código de > <> (uma linguagem de programação esotérica) foi retirado de seu ambiente natural. Essa mudança o tornou incapaz de se movimentar da maneira que costumava: o que costumava ser um movimento toroidal foi restrito ao simples movimento da esquerda para a direita. Mas os programas ainda são escritos como se os peixes fossem capazes de se mover através deles. É sua tarefa, prezado programador, escrever um programa para linearizar um programa> <>. E faça isso no menor número de bytes possível; peixes não têm memórias muito grandes.

Movimento em> <>

Em> <>, o movimento é toroidal e um caractere de cada vez. Isso significa que o peixe (o ponteiro) pode "enrolar" do final de uma linha até o início. Em> <>, o peixe também é capaz de se mover de cima para baixo, de baixo para cima e da direita para a esquerda, em contraste com a maneira como a maioria dos ponteiros se move. Portanto, esse padrão de movimento seria válido:

>>>^  >>>v
   >>>^  v

e terminaria em um loop infinito (retornando à linha superior assim que ultrapassar o fundo infinitamente).

O peixe se move em uma grade de comprimento igual a max (comprimento da linha) e altura igual ao número de linhas.

Como você descobre para onde o peixe se move? Estes comandos alteram o vetor de direção do movimento (por exemplo, (-1,0)significa da direita para a esquerda):

Command | Direction Change
---------------------------
   >    | (1,0) (default)
   <    | (-1,0)
   ^    | (0,1)
   v    | (0,-1)
   /    | (x,y) -> (y,x)
   \    | (x,y) -> (-y,-x)
   |    | (x,y) -> (-x,y)
   _    | (x,y) -> (x,-y)
   #    | (x,y) -> (-x,-y)
   ;    | (0,0)

Como observado, o peixe começa a se mover da esquerda para a direita, ou seja, com o vetor de direção (1,0). O peixe começa a analisar os comandos começando com o primeiro comando que vê e muda de direção se um comando corresponder a um dos alteradores de direção acima mencionados.

O peixe para de se mover quando vê um ;e termina o programa.

Entrada

A entrada será um programa válido (por exemplo, não em loop infinito) fornecido através do STDIN. Você também pode ler um arquivo, se desejar. As linhas de cada programa não terão necessariamente o mesmo comprimento.

A entrada é fornecida como uma sequência, com novas linhas separando cada linha do programa.

Os programas não serão repetidos, o que também significa que sempre terminarão com a ;.

Saída

A saída será o programa linearizado. Ou seja, você deve retornar todos os caracteres (incluindo trocadores de direção) que o peixe veria se executasse o programa "normalmente". Este é todos os caracteres em seu caminho para o ;.

Se a entrada possui linhas de comprimento desigual e o peixe acaba se movendo ao longo de uma linha menor que o comprimento da linha mais longa, você deve tratá-lo como se o peixe estivesse se movendo sobre um espaço (consulte os casos de teste).

Os familiarizados com> <> saberão que os trocadores de direção não são a única maneira de fazer movimento, mas, por uma questão de simplicidade, trate a entrada como se fosse a única maneira de afetar o movimento.

Regras

  1. Aplicam-se brechas padrão
  2. Você pode escrever um programa ou função completo
  3. A entrada é fornecida através de STDIN ou um arquivo como uma sequência que contém as linhas do programa separadas por novas linhas ( \n)
    • Você pode entender a entrada de maneira diferente, dentro do razoável (fique à vontade para me perguntar se você tem um tipo específico de entrada em mente). Você não pode preencher a entrada com espaços para que os comprimentos da linha correspondam.
    • Consulte esta meta post sobre entrada flexível. No que se refere à publicação, o consenso geral deve ser o mais flexível possível dentro do razoável.
  4. A saída é uma sequência única através de STDOUT ou retornada pela função (dependendo do que você escolher, consulte a Regra 2)

Casos de teste

v     >v
>abcv//;
gfed<^ih

v>abcv<defghi^//>v;



v     >v
>abcv//;
gfed<^

v>abcv<defg  ^//>v;


abcdef;

abcdef;


abcd|;

abcd|dcba;


abcd#;

abcd#dcba;


abcd\;
    _

abcd\_\dcba;


^;
>abcde/
 ^jihg<

^ >abcde/ <ghij^a;


;

;
Cole
fonte
2
Podemos considerar a entrada como uma matriz de strings?
Lucas
2
Podemos assumir que o primeiro caractere (o superior esquerdo) não será um ponto e vírgula?
Kritixi Lithos 26/03
1
@KritixiLithos boa pergunta, eu vou dizer que você não pode assumir isso. Vou adicionar um caso de teste.
cole
1
@ Lucas, você pode considerar a entrada como uma matriz de seqüências de caracteres se for muito difícil ou impossível operar no formato de entrada (sequência com linhas separadas por novas linhas). Veja a regra 3. agora adicionada
cole
3
Upvote obrigatória para lógica absurda
Patrick Roberts

Respostas:

13

Röda , 405 393 392 391 371 366 361 236 234 232 230 223 200 bytes

F f{L=f()|[#_]|sort|tail
c=""x=0
y=0
X=1
Y=0{l=f[y]l.=[" "]*(L-#l)c=l[x]a=X
[c]
C=indexOf(c,`><v^/\|_#`)X=[1,-1,0,0,-Y,Y,-X,X,-X,X][C]Y=[0,0,1,-1,-a,a,Y,-Y,-Y,Y][C]x+=X
x=x%L
y+=Y
y=y%#f}until[c=";"]}

Experimente online!

Verifique as saídas!

Explicação (desatualizada)

F f{                          /* Declares a function F with parameter f */
                              /* Takes a 2D array of single-char Strings as f */
L =                           /* L contains the value of the length of the longest line*/
    f()                       /* Push the contents each element of f to the stream; this pushes each line*/
        | [#_]                /* Pull a line and push its length to the stream*/
               |sort|tail     /* Sort it and get the last value (the largest one) */
c=""                          /* c contains the value of the current char that is being processed */
x=0; y=0                      /* x and y contain the position of the fish */
X=1; Y=0                      /* X and Y contain the direction of the fish */
{ ... }while [c != ";"]       /* While c is not `;` do: */
l=f[y]                        /*  l is the line (row) the fish is at */
c=" " if [x >= #l]            /*  If x is more than or equal to the line's length, set c to a space (so that we don't need to pad spaces to the array at the beginning)*/
else c = l[x]                 /*  Else set c to the character a position x of l*/
[c]                           /*  Push c to the output stream; ie prints c without a trailing newline*/
a = X                         /*  a preserves the value of X before analysing c */
C = indexOf(c,`><v^/\|_#`)    /*  Simple enough */
X=[1,-1,0,0,-Y,Y,-X,X,-X,X][C]/*  Map each value of C to their respective X-direction in the array */
                              /*  If c cannot be found in `><v^/\|_#` then it will be given the value of -1, or in other words, the -1th element of an array its last element */
Y=[0,0,1,-1,-a,a,Y,-Y,-Y,Y][C]/*  Do the same thing for Y */
x += X                        /*  Change the x-pos by the X-direction */
x = x%L                       /*  Wrap around the right edge */
y += Y                        /*  Do the same for y */
y=y%#f                        /*  But wrap around the bottom instead */
x+=L if[x<0]                  /*  Wrap around the left */
y+=#f if[y<0]                 /*  Wrap around the top */
}

Edições

  • 10 bytes salvos graças ao @fergusq usando em %vez de verificar se x ou y está além dos limites, o que abriu caminho para mais 2!
  • Usado em `\`vez de"\\"
  • Movido c=""para a segunda linha e, em seguida, removeu a nova linha após ela
  • Movida a conversão das linhas para a matriz de caracteres únicos nos loops, em vez de no início (inspirada na resposta do Python)
  • Usou a sintaxe do whilecolchete de (obrigado a @fergusq por detectar isso)
  • Removido as a=Xdeclarações if
  • Agradecemos a @fergusq por encontrar uma maneira mais curta de encontrar o comprimento da linha mais longa
  • Sintaxe de matriz usada em vez de instruções if (como a resposta do Python) para economizar toneladas de bytes
  • Removido o código que preenchia os espaços. Em vez disso, os espaços são adicionados à medida que o> <> se move
  • Corrigido um bug graças e jogou um personagem graças a @fergusq
  • Removido o código +1no final indexOfe reestruturado para salvar 2 bytes
  • Economizou 2 bytes movendo as coisas (graças a @fergusq novamente)
  • Economizou 1 byte graças a @fergusq usando um método diferente de preenchimento de espaços
  • Economizou 1 byte usando em until[c=";"]vez dewhile[c!=";"]
  • Graças a uma dica do @fergusq, removi o loop que preenche os espaços e o substitui por l.=[" "]*L
  • Salva mais de 20 bytes removendo as instruções if no final que envolvem o programa nas bordas esquerda e superior
Kritixi Lithos
fonte
Eu acho que você pode salvar alguns bytes usando em x=((x+X)%#l)vez de x+=X. Infelizmente, (-1)%#lainda retorna -1.
fergusq
@fergusq Golfed sua sugestão :)
Kritixi Lithos
Você pode usá-lo com ymuito: y=y%#f.
fergusq
@fergusq estava prestes a acrescentar que :)
Kritixi Lithos
Pensei mais nisso, aqui estão duas outras dicas de golfe: use em keyvez de cmpe use em {...}while[...]vez de while[...]do ... done.
Fergusq
10

Python 2, 262 243 237 235 234 233 231 221 219 218 217 bytes

Aceita entrada como ['<line_1>', '<line_2>', ...]

i=input()
q=max(map(len,i))
i=[k+' '*q for k in i]
x=y=k=0
j=1
o=''
while';'not in o:r=[1,-1,-j,-k,0,0];o+=i[y][x];l='><#\\v^/|_'.find(o[-1]);a=(r+[k,-j,j])[l];k=([k,-k,k,j]+r)[~l];j=a;x=(x+j)%q;y=(y-k)%len(i)
print o

Experimente Online!

-19 bytes graças a @math_junkie
-6 bytes graças a @ThisGuy
-2 bytes extraindo max(map(L,i))para uma variável (porque teoricamente é usada duas vezes).
-1 byte, reduzindo o número de vezes que i[y][x]aparece.
-1 byte usando '\x00'para que eu não precise fazer a [1:]parte da o[1:]saída
-2 bytes usando em \0vez de \x00
-10 bytes, graças ao @KritixiLithos por perceber que eu posso preencher o quanto quiser do lado direito, porque o extra será ignorado
(não mudança byte) bug fixo porque variável extraído estava fora de lacete
-2 bytes porque agora só uso len2 vezes de modo a reatribuição leva 2 bytes adicionais
-2 byte, usando while';'not in oem vez dewhile o[-1]!=';'e usando em o=''vez de o='\0'. Isso não apenas salva 2 bytes, mas também elimina o byte nulo principal, que tecnicamente não era realmente válido.

Explicação

i = input()                       # Takes input as an array of strings
q = max(map(len,i))               # Finds the width of the longest line
i = [k + ' ' * q for k in i]      # Makes sure everything is at least that width
x = y = k = 0                     # Set the point to (0, 0). Set the vertical motion to 0
j = 1                             # Set the horizontal motion to 1
o = '\0'                          # Initialize the output to a null byte (this is output as nothing, so it doesn't actually affect output)
while o[-1] != ';':               # While the last character in the output is not ';' (this is why the output needs to be initialized with something, otherwise o[-1] gives an index error)
    r = [1,-1,-j,-k,0,0]          # Some of the vertical and horizontal coordinates correspond in opposite order
    o += i[y][x]                  # Add the current character to the output
    l = '><#\\v^/|_'.find(o[-1])  # Find the index of the current character here (or -1 if it's just a regular character)
    a = (r + [k, -j, j])[l]       # The fancy array contains the horizontal movement for each control character
    k = ([k, -k, k, j] + r)[~l]   # The fancy array contains the vertical movement for each control character. Using ~l to get the right index, because r has the values backwards
    j = a                         # a was a placeholder because otherwise k would not be correct
    x = (x + j) % q               # Adjust the pointer position
    y = (y - k) % len(i)          # Adjust the pointer position
print o                           # Print the output after the loop is finished
HyperNeutrino
fonte
Você pode jogar fora os retornos trydesde se não for encontrado: TIOfind-1
junkie de matemática 27/03
@math_junkie Oh ok, obrigado!
HyperNeutrino 27/03
Você pode atribuir lena uma variável, por exemplo, Lpara salvar 3 bytes e outros 4, alterando a atribuição de 0múltiplas linhas para 1 linha x=y=k=0.
caird coinheringaahing
@ThisGuy Thanks!
HyperNeutrino 27/03
2
@Cole No meu golfe sugerido, adicionei j e k ao final de cada array. Isto é assim que a direção é mantida
matemática viciado
5

Ruby, 274 200 187 183

Raspou apenas mais alguns caracteres soltando a matriz de momento d,.

Estou muito orgulhoso deste. Isso foi divertido! Ele pega uma matriz de strings e retorna a string apropriada.

->a{o,x,y='',-1,0
b,m=1,0
(o+=n=a[y=(y+m)%a.size][x=(x+b)%(a.map &:size).max]||' '
b,m=([1]+[0,-1,0]*2+[1,-m]+[-b,m,b]*2+[-m,-b,-m,b,m])[2*('><^v/\\|_#'.index(n)||9),2])until o[?;]
o}

Comentado abaixo.

->a{
    o,x,y='',-1,0  # o is the output string, x and y are the positions in the array
    b,m=1,0          # b and m are the direction of momentum
    until o[?;] # until o contains a semicolon
        w=(a.map &:size).max # w is the max width of the arrays
        h=a.size    # h is the height of arrays
        x=x+b % w   # increment cursor position
        y=y+m % h
        o+=n=a[y][x]||' ' # add the new char (or " ") to o
        ix=2*('><^v/\\|_#'.index(n)||9) # find the index new char in the string
        b,m=([1]+[0,-1,0]*2+[1,-m]+[-b,m,b]*2+[-m,-b,-m,b,m])[ix,2] # set momentum to its new value
    end
    o # return output string
}
Não que Charles
fonte
1

PHP 7, 291 260 bytes

for($m=max(array_map(strlen,$z=explode("
",$argv[1]))),$y=0,$r=count($z)-$v=1;';'!=$c;[$v,$w]=[[$v,1,-1,0,0,-$w,$w,-$v,$v,-$v][$o=strpos(' ><^v/\|_#',$c)],[$w,0,0,-1,1,-$v,$v,$w,-$w,-$w][$o]],$x+=$m+$v,$x%=$m,$y=0<=($y+=$w)?$r<$y?:$y:$r)echo$c=$z[$y][$x]??' ';
chocochaos
fonte
Eu conto 291 bytes / caracteres.
HyperNeutrino 28/03
Você está correto, eu falhar em contar aparentemente = P
chocochaos
Hah Não se preocupe, eu também fiz isso.
HyperNeutrino 28/03
Encontrei algumas coisas no golfe, diminuindo isso de 25% para 218 bytes. Não testado, mas definitivamente vale a pena dar uma olhada .
Titus
2
uma falha em um dos meus jogos de golfe e mais seis bytes jogados: lista de golfe atualizada .
Titus
1

JavaScript, 242 236 235 231 220 bytes

a=>{n=a.length;m=x=y=p=0;a.map(g=>m=(w=g.length)<m?m:w);q=1,o="";while((t=a[y][x]||" ")!=";")o+=t,h=q,q=[q,1,0,p,-q][(s=">v\\| <^/_#".indexOf(t)+1)%5]*(r=s>5?-1:1),p=[p,0,1,h,p][s%5]*r,x=(x+q+m)%m,y=(y+p+n)%n;return o+t}

Experimente online!

fəˈnɛtɪk
fonte
você pode salvar 13 caracteres se você pegar a string como uma matriz. As especificações foram alteradas.
Não que Charles,