Código Golf: Sua própria cobra ASCII horizontal


29

Muito inspirado por esse desafio Code Golf: Sua própria cobra ASCII de estimação - eu pensei que fazê-la horizontal acrescentaria uma camada extra de complexidade.

Um exemplo de cobra horizontal:

            0 0               
  0        0 0 000            
00 0     00       000 0      0
    000 0            0 0   00 
       0                000   

E as regras são:

  1. São impressas exatamente 5 linhas de caracteres
  2. Cada linha tem exatamente 30 caracteres, consistindo em uma combinação de espaços e o personagem com o qual você escolhe desenhar sua cobra.
  3. Sua cobra começa na linha 3
  4. A próxima linha a ser usada para desenhar sua cobra deve ser escolhida aleatoriamente a partir da sua linha atual, uma linha acima (se você ainda não estiver na linha 1) ou uma linha abaixo (se você ainda não estiver na linha 5).
    • Essas opções devem ser igualmente ponderadas. Portanto, se você estiver na linha 1, terá 50% de chance de permanecer na linha 1 e 50% de chance de passar para a linha 2. Se estiver na linha 2, 33% de chance de passar para a linha 1, 33% de chance de permanecer na linha 2 ou 33% de chance de passar para a linha 3
  5. Sua cobra não precisa visitar todas as linhas.

5
Bem-vindo ao PPCG! Este é um bom primeiro desafio.
Giuseppe

Para esclarecimento, se estamos no limite, temos que escolher uniformemente (permanecer na mesma linha) e (ir para uma linha diferente) ou podemos ter pesos não uniformes?
Giuseppe

E além das bordas, temos que pegar / abaixar / mesma linha uniformemente?
Giuseppe

2
Mmm ... pelo menos a limitação de 5 linhas impede as pessoas de roubar respostas da outra com uma transposição anexada.
Magic Octopus Urn

9
A rotação física do monitor em 90 ° conta como um byte? : D
Eric Duminil

Respostas:


11

JavaScript (ES6), 98 bytes

Guardado 7 bytes graças a @KevinCruijssen

Retorna uma matriz de 5 strings.

f=(y=2,a=[...'  0  '])=>a[0][29]?a:f(y+=(Math.random()*(y%4?3:2)|0)-!!y,a.map((v,i)=>v+=i-y&&' '))

Experimente online!

Comentado

f = (                       // given:
  y = 2,                    //   y = current line (0-indexed)
  a = [...'  0  ']          //   a[] = array of 5 lines
) =>                        //
  a[0][29] ?                // if all columns have been processed:
    a                       //   stop recursion and return a[]
  :                         // else:
    f(                      //   do a recursive call with:
      y += (                //     the updated value of y, to which we add -1, 0 or 1:
        Math.random() *     //       pick a random value in [0,1)
        (y % 4 ?            //         if y is neither 0 or 4:
          3                 //             multiply it by 3
        :                   //           else:
          2                 //             multiply it by 2
        ) | 0               //       force an integer value
      ) - !!y,              //     subtract either 0 or 1
      a.map((v, i) =>       //     for each value v at position i in a[]:
        v += i - y && ' '   //       append either '0' if i = y or a space otherwise
      )                     //     end of map()
    )                       //   end of recursive call

Você pode soltar de usar ((y%4?3:2)|0)-(y>0)para -6 bytes. Experimente online.
Kevin Cruijssen 22/02

Correção: -7 bytes. O 1in new Random(...)está implícito por padrão, é claro. Experimente online.
Kevin Cruijssen 22/02

@KevinCruijssen Thanks! ( !!yEm vez de (y>0)poupa mais de 2 bytes.)
Arnauld

7

Carvão , 28 bytes

P|   F³⁰«0≡ⅉ²M‽²↑±²M‽²↓M⊖‽³↓

Experimente online! Link é a versão detalhada do código. Explicação:

P|   

Imprima um pouco de preenchimento para forçar 5 linhas de saída.

F³⁰«

Repita 30 vezes.

0

Imprima um zero (e mova horizontalmente).

≡ⅉ²M‽²↑

Se a coordenada Y for 2, mova para cima aleatoriamente por 0 ou 1.

±²M‽²↓

Se for -2, desça aleatoriamente por 0 ou 1.

M⊖‽³↓

Caso contrário, desça aleatoriamente por -1, 0 ou 1.


6

Perl, 68 bytes

perl -E '$%=2;s:$:$n++%5-$%&&$":emg,$%-=!!$%+rand!($%%4)-3for($_=$/x4)x30;say'

Isso não parece ótimo.


5

Gelatina , 24 bytes

3µ’o1r‘«5¥$Xµ30СṬ€o⁶z⁶Y

Experimente online!

Explicação

3µ'o1r '«5 ¥ $ Xµ30СṬ € o⁶z⁶Y || Programa completo niládico.
                         ||
3 || A partir de 3 ...
 µ µ30 || ... Executar 30 vezes ...
               |¡ || ... E colete os resultados em uma lista.
  'o1r' «5 ¥ $ X || - | Função "auxiliar" monádica.
  'o1 || - | O número inteiro atual, decrementado OR 1.
     r X || - | Pegue um item aleatório do intervalo de ^ a ...
      «« 5 || - | ... O número incrementado, limitado a 5 (usa no máximo).
         ¥ $ || - | Elementos de sintaxe. Usado para agrupar links.
                 | € || Inverta cada.
                   o⁶ || OU lógico com um único espaço.
                     z⁶ || Transponha com espaços de preenchimento.
                       Y || Adira por novas linhas.

5

R , 138 bytes

m=matrix(" ",30,5)
m[1,3]=0
x=3
s=sample
for(i in 2:30)m[i,x<-x+(-1)^(x==5)*s(0:1,1)*x%in%c(1,5)+(s(3,1)-2)*x%in%2:4]=0
write(m,"",30,,"")

Experimente online!

Handily outgolfed by plannapus


5

Python 3, 144 bytes

@Ruts, @Turksarama e @mypetlion foram muito úteis na redução de bytes

import random
m=[list(' '*30)for y in range(5)]
l=2
for i in range(1,30):
 m[l][i]=0
 l+=random.randint(~-(l<1),l<4)
for j in m:
  print(*j)

Vai tentar melhorar isso. Desafio divertido!


3
Mude l+=random.randint(-1,1) l=0 if l<0 else l l=4 if l>4 else lpara l+=random.randint(~-(l<1),l<4)para salvar 31 bytes.
21818 mypetlion

11
Você deve poder remover muitos espaços e novas linhas.
Sr. Xcoder

11
Mude m=[[' 'for x in R(w)]for y in R(h)]para m=[list(' '*w)for y in R(h)]para salvar 7 bytes.
21818 mypetlion

2
Em python, booleanuma subclasse de int. Então, Falsepode ser usado no lugar de 0e Truepode substituir 1. O ~operador é unário por bit a bit note o -operador vira o sinal (multiplique por -1). Portanto, ~-(False)avalia -1e ~-(True)avalia como 0. #:
mypetlion

11
Atribua seu 0 inicial dentro do seu loop e defina l após a atribuição. Isso economiza uma linha inteira ( m[2][0]=0desapareceu) e 2 bytes no loop for ( for i in R(1,30):torna-se for i in R(30):). Você também precisará recalcular l depois de definir o 0. Isso deve levar a 144 bytes.
Turksarama

4

R , 120 114 bytes

m=matrix
r=m(" ",30,5)
x=3
for(i in 1:30){r[i,x]=0;x=x+sample(-1:1,1,,m(c(0,rep(1,13)),3)[,x])}
write(r,"",30,,"")

Obrigado a Giuseppe pelos 6 bytes adicionais!

Usa uma tabela de probabilidades da seguinte maneira:

> matrix(c(0,rep(1,13)),3)
     [,1] [,2] [,3] [,4] [,5]
[1,]    0    1    1    1    1
[2,]    1    1    1    1    1
[3,]    1    1    1    1    0
Warning message:
In m(c(0, rep(1, 13)), 3) :
  data length [14] is not a sub-multiple or multiple of the number of rows [3]

onde cada coluna corresponde a um caso, ou seja, a coluna 1 é escolhida se a cobra estiver na linha 1, dando probabilidades 0, 1/2 e 1/2 para escolher respectivamente -1 [descer], 0 [ficar parado] e 1 [ subir] ( samplenormaliza automaticamente as probabilidades para 1), a coluna 2 da linha 2 fornece probabilidades 1/3, 1/3 e 1/3, etc ...

Experimente online!



@Giuseppe Thanks! Havia de fato nenhuma razão para o alias, e eu esqueci de usar a reciclagem vector para esse extra 0.
plannapus

3

SOGL V0.12 , 22 21 bytes

3ā'∑∫⁵╗ž⁴H1ΧGI5χ⁴-ψ+;

Experimente aqui!

Explicação:

3                      push 3
 ā                     push an empty array - the canvas
  '∑∫                  30 times do, pushing counter            | stack = 3, [], 1
     ⁵                   duplicate the Y coordinate            | stack = 3, [], 1, 3
      ╗ž                 at those coordinates insert "+"       | stack = 3, ["","","+"]
        ⁴                duplicate from below                  | stack = 3, ["","","+"], 3
         H               decrease                              | stack = 3, [...], 2
          1Χ             maximum of that and 1                 | stack = 3, [...], 2
            G            get the item 3rd from top             | stack = [...], 2, 3
             I           increase it                           | stack = [...], 2, 4
              5χ         minimum of that and 5                 | stack = [...], 2, 4
                ⁴-       subtract from the larger a copy of the smaller value | stack = [...], 2, 2
                  ψ      random number from 0 to pop inclusive | stack = [...], 2, 2
                   +     add those                             | stack = [...], 4
                    ;    and get the array back ontop          | stack = 4, ["","","+"]

                         implicitly output the top item - the array, joined on newlines

3

Japonês, 31 29 bytes

Retorna uma matriz de linhas.

30ÆQùU±[2V=Jõ VVJò]mö i3 gUÃy

Teste-o




2

Oitava com pacote de estatísticas, 99 bytes

Também funciona no MATLAB com a caixa de ferramentas estatísticas.

p=3;for k=1:29
p=[p;p(k)+fix(randsample(setdiff([1 pi 5],p(k)),1)-3)/2];end
disp(['' (p==1:5)'+32])

Experimente online!



2

SmileBASIC, 107 105 103 89 bytes

FOR I=0TO 29FOR J=0TO 5LOCATE I,J?" 0"[Y+2==J]NEXT
Y=Y+RND(3)-1D=Y/3>>0Y=Y-D-D*RND(2)NEXT
NEXT

Essa resposta é mais interessante que a vertical por causa dos casos de borda (literais).

64 bytes, sem espaços de impressão:

FOR I=0TO 29LOCATE,Y+2?0;
Y=Y+RND(3)-1D=Y/3>>0Y=Y-D-D*RND(2)NEXT

Eu também encontrei algumas variações da linha 2 com o mesmo comprimento:

Y=Y+RND(3)-1D=Y/3>>0Y=Y-D-D*RND(2)NEXT
Y=Y+RND(3)-1D%=Y/3Y=Y-D%-D%*RND(2)NEXT
Y=Y+RND(3)-1Y=Y-Y DIV 3*(RND(2)+1)NEXT
Y=Y+RND(3)-1Y=Y/3OR.Y=Y-D-D*RND(2)NEXT

A divisão inteira de Y / 3 é usada para verificar se Y está fora do intervalo válido e para obter o sinal.


2

Java 8, 177 170 bytes

v->{int a[][]=new int[5][30],c=0,r=2;for(;c<30;r+=Math.random()*(r%4>0?3:2)-(r>0?1:0))a[r][c++]=1;String R="";for(int[]y:a){for(int x:y)R+=x<1?" ":"~";R+="\n";}return R;}

-7 bytes graças a @ OlivierGrégoire .

Explicação:

Experimente online.

v->{                // Method with empty unused parameter and String return-type
  int a[][]=new int[5][30],
                    //  Integer-matrix of size 5x30
      c=0,          //  Column, starting at index 0
      r=2;          //  Row, starting at index 2
  for(;c<30;        //  Loop `c` 30 times
      r+=Math.random()*(r%4>0?3:2)-(r>0?1:0))
                    //    After every iteration: change `r` with -1,0,1 randomly
                    //     If `r` is 0: random [0;2)-0 → 0,1
                    //     If `r` is 4: random [0;2)-1 → -1,0
                    //     If `r` is 1,2,3: random [0:3)-1 → -1,0,1
    a[r][c++]=1;    //   Fill the cell at indices `r,c` from 0 to 1
  String R="";      //  Result-String, starting empty
  for(int[]y:a){    //  Loop over the rows of the matrix
    for(int x:y)    //   Inner loop over the individual column-cells of the matrix
      R+=x<1?       //    If the value of the cell is still 0:
          " "       //     Append a space
         :          //    Else (it's 1):
          "~";      //     Append the character
    R+="\n";}       //   After every row, Append a new-line
  return R;}        //  Return the result-String

11
r+=Math.random()*(r%4>0?3:2)-(r>0?1:0)para salvar alguns bytes.
Olivier Grégoire

@ OlivierGrégoire Eu pensei que já tinha feito isso, mas aparentemente não. Talvez eu tenha feito isso em outra resposta recentemente ..: S Obrigado!
Kevin Cruijssen

2

C (gcc) , 134 130 bytes

r,x,y=3,a[31],m;f(){for(x=0;x<31;x++){m?putchar(x==30?10:a[x]-m?32:48):(a[x]=y);r=rand();y+=y==1?r%2:y==5?-r%2:1-r%3;}++m<6&&f();}

Experimente online!


Bem-vindo ao PPCG!
Martin Ender

Obrigado! Usar putchar em vez de printf economiza 4 bytes.
MaSi

1

Python 3 , 123 bytes

from random import*
i,*a=2,
exec("a+=i,;i+=randint(-(i>0),i<4);"*30)
for x in range(5):print(''.join(' 0'[x==i]for i in a))

Experimente online!

Gere uma matriz de números inteiros e converta-a em cada linha.

Python 2 , 120 bytes

from random import*
i=2;a=[]
exec"a+=i,;i+=randint(-(i>0),i<4);"*30
for x in range(5):print''.join(' 0'[x==i]for i in a)

Experimente online!

No Py2, o redundante analisa exece printpode ser removido, mas a sintaxe na 2ª linha é inválida.

Superando a finalização de Py2 por Rod e Py3 por linemade .


1

Ruby , 98 77 bytes

->{a=(0..4).map{" "*30}
x=2
30.times{|i|a[x][i]=?@
x+=rand(3-17[x])-30[x]}
a}

Experimente online!

Um lambda retornando uma matriz de seqüências de caracteres.

Meu impulso inicial foi gerar as colunas e transpor essas colunas, mas é muito mais fácil evitar essa etapa.

Eu gostaria de inicializar acom [" "*30]*5, mas isso faria cópias rasas das cordas, resultando em uma cobra muito gorda e não escorregadia.

Eu poderia ter usado uma constante como Do incremento (para a mesma contagem de bytes), mas Ruby reclamaria toda vez que eu a designasse. Decidi que preferia diminuir a legibilidade reutilizando o imeio do loop a ter vários avisos de depuração para ignorar.

Eu também gostaria de economizar alguns bytes loop{x+=rand(3)-1;(0..4)===x&&break}, mas isso causaria um viés nas bordas: 1/3 de chance de voltar para dentro, 1/3 de chance de permanecer e 1/3 de chance de sair dos limites por um tempo antes de eventualmente voltar aleatoriamente (ou seja, "ficar").

-20 bytes: use Ruby Integer#[]para criar condicionais minúsculos, garantindo pesos de movimento corretos para todas as 5 posições. Isso substitui um padrão de quebra de loop (com uma chance diferente de zero de não parar) para uma economia enorme. Obrigado, Eric Duminil !

-1 byte: Inicialize acom em (0..4).mapvez de 5.times, obrigado novamente por Eric Duminil .

->{
  a = (0..4).map{ " " * 30 }      # a is the return array: 5 strings of 30 spaces
  x = 2                           # x is the snake position
  30.times{ |i|                   # For i from 0 to 29
    a[x][i] = ?@                  #   The ith position of the xth row is modified
    x += rand(3 - 17[x]) - 30[x]  #   Using bit logic, add rand(2 or 3) - (0 or 1)
  }
  a                               # Return the array of strings
}

Bom começo. Não há necessidade de um interior loop. Você pode calcular o incremento com rand(2+14[x])-30[x]ou rand -(30[x])..15[x]. Provavelmente há uma versão mais curta. Ainda assim, -20 bytes não é ruim! Experimente online!
Eric Duminil

1 byte a menos com x,a=2,(0..4).map{" "*30}. Experimente online!
Eric Duminil

11
Uau, 30[x]é um ótimo truque! Obrigado!
benj2240

1

Perl 6 , 85 bytes

.join.say for [Z] ((' ',' ',0,' ',' '),{.rotate(set(0,+?.[0],-?.[4]).pick)}...*)[^30]

Experimente online!

A expressão longa entre parênteses é uma sequência lenta gerada a partir do elemento inicial (' ', ' ', 0, ' ', ' '), a primeira faixa vertical da saída. Cada tira / lista sucessivo é gerado a partir do precedente, chamando seu rotatemétodo, com o deslocamento escolhido aleatoriamente a partir de um conjunto contendo 0, 1(se o primeiro elemento é diferente de zero), e -1(se o quinto elemento é diferente de zero).

A matriz de tiras horizontais é transposta com o [Z]operador, transformando-a em uma lista de tiras verticais, cada uma das quais é então joineditada em uma única seqüência e é gerada com say.


1

Scala, 207 bytes

val b=Array.fill(150)('.')
def s(y:Int,x:Int)={val r=Random.nextInt(6)
val z=y+(if(y>3)-r%2
else if(y<1)r%2
else r/2-1)
b(z*30+x)='$'
z}
(3/:(0 to 28))(s(_,_))
b.mkString("").sliding(30,30).foreach(println)

amostra:

...................$$$...$.$$.
.$$$..............$...$.$.$...
$...$$$..$...$$.$$.....$......
.......$$.$.$..$..............
...........$..................

degolfado:

val buf = List.fill(150)('.').toBuffer
def setRowCol (y:Int, x:Int): Int = {
  val r = Random.nextInt(6)
  val z = y + (
    if (y>3) 
        -(r%2)
    else if (y<1) 
        (r%2)
    else 
        r/2-1
  )
  buf (z * 30 + x) = '$'
  z
}
(3 /: (0 to 28)(setRowCol (_, _))
println 
buf.mkString ("").sliding(30,30).foreach(println)

Minha invenção única - bem, eu não li as outras soluções até agora, é gerar um Random (6) que é implicitamente dois Randoms (2 * 3). Se estiver longe da fronteira, utilizo os valores de r / 2 (0,1,2) e → (-1,0,1) para subir ou descer. Se na fronteira, posso evitar o chamado caro do personagem de outro aleatório, e apenas pegar o módulo (2) para decidir se devo ficar ou devo ir.

Vamos ver as outras soluções. :)


Sim, imagem de amostra errada. Faz. :)
usuário desconhecido

rochas scala! oh .. codigo de golfe .. caso de uso errado ele aparece .. Como diabos ele passou por isso java?
Javadba

@javadba: Você clicou no try itlink? Kevin Cruijssen não incluiu alguns boilerplate, necessários para compilar esse código ou executá-lo no JShell, mas acho que isso está de acordo com as diretrizes - pode haver uma meta-discussão. Se preferir, você pode tentar reduzir esse código usando também uma matriz de duas dimensões. Uma segunda idéia é reduzir o código deslizante no final. Algum método de mapa? O println está oculto por Kevin. - Sim, a matriz fornece uma melhoria em 8. #
user unknown

Deixe scala inferir o tipo de retorno int: Salvo mais 4 caracteres.
usuário desconhecido

por isso é entrar no estádio para java agora
javadba

1

Perl, 83 101 bytes

perl -E '$l=3;map{map$s[$_-1].=/$l/?0:" ",1..5;$l-=1-int 3*rand;$l=~y/60/51/}1..30;say for@s'

Novo: sem problema de probabilidade nas fronteiras:

perl -E '$l=3;map{map$s[$_-1].=/$l/?0:" ",1..5;$l=int($l<2?1+2*rand:$l>4?6-2*rand:$l-1+3*rand)}1..30;say for@s'

Ungolfed:

$l=3;                             #start line
map{
  map $s[$_-1].=/$l/?0:" ",1..5;  #0 at current char and line, space elsewhere
  $l-=1-int 3*rand;               #up, down or stay
  $l=int( $l<2 ? 1+2*rand
        : $l>4 ? 6-2*rand
        :        $l-1+3*rand )    #border patrol
}
1..30;                            #position
say for@s                         #output result strings/lines in @s

2
Sua patrulha de fronteira não oferece a probabilidade certa de 50% de permanecer no limite.
Ton Hospel

0

PowerShell , 133 bytes

$a=(,' '*30),(,' '*30),(,' '*30),(,' '*30),(,' '*30);$l=2;0..29|%{$a[$l][$_]=0;$l+=0,(1,($x=1,-1),$x,$x,-1)[$l]|Random};$a|%{-join$_}

Experimente online!

Constrói uma matriz 2D de 30 espaços de largura por 5 linhas de altura. (NB - se alguém puder encontrar uma maneira mais eficaz de inicializar esse array, eu irei <3 para sempre.) Define a variável auxiliar $lcomo 2(isso é usado para qual linha o segmento anterior da serpente estava). Em seguida, passa de 0para 29.

A cada iteração, definimos nosso elemento de cobra como 0. Então indexamos em uma matriz complicada, Get-Randomque seleciona se aumentamos ou diminuímos ou permanecemos os mesmos. Isso foi adicionado novamente $l.

Finalmente, percorremos os cinco elementos de $ae -joinseus elementos internos em uma única sequência cada. Essas cinco strings são deixadas no pipeline, e o implícito Write-Outputnos fornece novas linhas de graça.


0

Clojure, 123 bytes

Aí vêm as parênteses:

(let[l(take 30(iterate #(max(min(+(-(rand-int 3)1)%)4)0)3))](doseq[y(range 5)](doseq[x l](print(if(= y x)0" ")))(println)))

Versão não destruída:

(let [l (take
       30
       (iterate
        #(max
          (min
           (+ (- (rand-int 3) 1) %)
           4)
          0)
        3))]
(doseq [y (range 5)]
  (doseq [x l]
    (print (if (= y x) 0 " ")))
  (println)))

Constrói uma lista das diferentes alturas do corpo da cobra e itera de 0 a 4. Sempre que uma altura corresponde à linha atual, ela imprime um 0, caso contrário, um espaço em branco. Não deixar as alturas excederem o limite realmente custa bytes. Também reconhecer quando uma nova linha está em ordem é mais intensivo em bytes, como deveria ser. Pode-se escrever facilmente um single doseq, produzindo um produto cartesiano dos x e y, mas não se sabe quando imprimir uma nova linha.


0

Python3 + numpy, 137 132 bytes

Não é o envio de python mais curto, nem o mais longo, e definitivamente não é o mais rápido.

from pylab import*
j=r_[2,:29]
while any(abs(diff(j))>1):j[1:]=randint(0,5,29)
for i in r_[:5]:print(''.join(' #'[c] for c in j==i))

atualizar Usando numpy's comando diff salvou 5 bytes para testar se a cobra é um padrão válido, em comparação com o cálculo da diferença manualmente com j[1:]-j[:-1].



0

R , 95 bytes

x=3;l=1:5
write(t(replicate(30,{y=ifelse(x-l,' ',0);x<<-sample(l[abs(x-l)<2],1);y})),'',30,,'')

A próxima linha xé sempre escolhida entre linhas que não estão a mais de 1 distância da linha atual ( l[abs(x-l)<2]). O uso em replicatevez de um forciclo salva alguns bytes necessários para a inicialização e manipulação da matriz e requer o uso do <<-operador ao atribuir à variável global x.

Experimente online!


0

05AB1E , 25 bytes

Y30F©ð5×0®ǝs<DÌŸ4ÝÃΩ}\)ζ»

Experimente online!

Explicação

Y                           # push the initial value 2
 30F                        # 30 times do
    ©                       # store a copy of the current value in register
     ð5×                    # push 5 spaces: "     "
        0®ǝ                 # insert 0 at the position of the current value
           s<DÌŸ            # push the range [current-1 ... current-1+2]
                4ÝÃ         # keep only numbers in [0 ... 4]
                    Ω       # pick one at random
                     }\     # end loop and discard the final value
                       )ζ   # transpose the list
                         »  # join by newlines
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.