Desenhar uma corda irregular


26

( Inspirado por este desafio .)

Digamos que temos uma string ABBCBA. Podemos dizer que há um aumento entre Ae B, a Bseguir A; podemos dizer que há uma corrida entre Be B, para nada muda; e finalmente podemos dizer que há uma queda entre Ce B. Podemos desenhar um gráfico como este:

             A   B   B   C   B   A
Rising:        o       o
Continuing:        o
Falling:                   o   o

Sem os rótulos e minimizando o espaço em branco:

o o
 o
   oo

Esta é a saída esperada para entrada ABBCBA.

Você pode usar qualquer caractere que não seja de espaço em branco para substituir ona saída. Além disso, cada coluna pode opcionalmente ter um espaço extra entre elas, assim:

o   o
  o 
      o o

A entrada consistirá em pelo menos três caracteres. A sequência será composta inteiramente por letras maiúsculas, mas você poderá usar letras minúsculas.

Casos de teste

TEST CASE
LINE 1
LINE 2
LINE 3

HELLOWORLD
 o oo o
  o
o    o oo

TESTCASE
 oo  o

o  oo o

EXAMINATION
o o o o o

 o o o o o

ZSILENTYOUTH
  o ooo o

oo o   o oo

ABC
oo



ABCBA
oo

  oo

Poderia haver um espaço entre cada os consecutivos ou a saída precisa ser compacta?
JungHwan Min 25/09/16

@JHM Claro, tudo bem.
Conor O'Brien

Além disso, a saída precisa ser uma sequência ou precisa ser semelhante ao exemplo?
JungHwan Min 25/09/16

@JHM O que você tem em mente?
Conor O'Brien

O código que tenho em mente gera uma grade.
JungHwan Min 25/09/16

Respostas:


6

Gelatina , 11 bytes

OIṠ“ o ”ṙZY

Experimente online! ou verifique todos os casos de teste .

Como funciona

OIṠ“ o ”ṙZY  Main link. Argument: s (string)

O            Ordinal; replace all characters with their code points.
 I           Increments; compute the differences of consecutive code points.
  Ṡ          Sign function.
   “ o ”ṙ    Rotate that string -1, 0, or 1 unit(s) to the left.
         Z   Zip; transpose rows and columns.
          Y  Join, separating by linefeeds.

11

Mathematica, 93 83 68 64 bytes

(usa 0 , não O)

Row[Column@Insert[{,},0,2-#]&/@Sign@Differences@LetterNumber@#]&

Explicação

LetterNumber@#

Obtém a posição no alfabeto de cada caractere da entrada.

Sign@Differences@

Toma a diferença entre cada elemento consecutivo e recebe o sinal ( -1para negativo / decrescente, 0para 0 / contínuo,1 positivo / crescente)

Insert[{,},0,2-#]&

Insere a 0em uma lista de doisNull s, na primeira posição se estiver subindo, no meio se continuar e na terceira posição se estiver caindo.

Row[Column@ ... ]

Formata a saída.


Se a saída puder parecer diferente da da pergunta, o código acima poderá ser reduzido para 41 bytes:

ListPlot@*Sign@*Differences@*LetterNumber

... que cria algo parecido com isto (para "ABBCBA"):

insira a descrição da imagem aqui


Como é a aparência de 41 bytes?
Conor O'Brien

@ ConorO'Brien, veja edit.
JungHwan Min 24/09/16

10

MATL , 15 , 14 bytes

dZSqtQtQv~79*c

Experimente online!

Explicação:

Dizem que uma imagem vale mais que mil palavras, então aqui está um intérprete beta online que mostra o valor no topo da pilha ao vivo à medida que é atualizado. Observe que ele ainda está na versão beta, portanto, pode ser necessário executar várias vezes.

Então, primeiro, chamamos dZS. dnos dá a diferença entre cada elemento consecutivo e ZSnos fornece o sinal (-1, 0 ou 1) de cada elemento. Portanto, com 'HELLOWORLD' como entrada, após o primeiro passo, teremos:

-1  1  0  1  1 -1  1 -1 -1

Agora, usamos apenas qpara diminuir isso e obter:

-2  0 -1  0  0 -2  0 -2 -2

E então duas vezes duplicamos a parte superior da pilha e incrementamos a matriz ( tQ). Depois disso, teremos

-2  0 -1  0  0 -2  0 -2 -2
-1  1  0  1  1 -1  1 -1 -1
0   2  1  2  2  0  2  0  0

Agora, todos os '0's são onde queremos gerar um caractere. Então, juntamos essas três matrizes em uma matriz ( v) e a negamos logicamente ( ~). Em seguida, multiplicamos cada valor na matriz pelo valor ASCII de 'O', ( 79*) e o exibimos como uma sequência com c.


Depois de ter o vetor [-1, 1, 0, 1, ...], você pode usá-los como índices de linha de uma matriz esparsa com índices de coluna [1,2,3,4, ...] e, em seguida, convertê-lo em uma matriz completa.
precisa saber é o seguinte

OK Nevermind, tentou essa sugestão, não parece salvar nada
Nick Alger

@NickAlger Obrigado pela dica de qualquer maneira! Por curiosidade, eu poderia ver o que você inventou?
DJMcMayhem

Certo. O seguinte é de 19 caracteres, embora provavelmente poderia ser melhorado um pouco, dZS2 + tn:? TNZ XPg79 * c
Nick Alger

Chegou a 16 com algumas otimizações, dZSqq_tn: lZ? 79 * c #
Nick Alger

8

Haskell, 63 bytes

f w=[do(e,y)<-zip w$tail w;max" "['o'|b e y]|b<-[(<),(==),(>)]]

Retorna uma lista de três strings, representando as linhas de saída. Não contém mensagens subliminares.

dianne salvou três bytes usando donotação e maxnão uma compreensão de lista e last.


3
Ótimo, não contém mensagens subliminares! O que são aqueles?
Conor O'Brien

5
['o'|b e y]...
izabera 25/09/16

Sim, meu mestre Espere o que está acontecendo?
CalculatorFeline

7

CJam , 19 bytes

l2ew{:-g)S3*0t}%zN*

Usa em 0vez de o.

Experimente online!

Explicação

l      e# Read input.
2ew    e# Get all pairs of consecutive letters.
{      e# Map this block over the pairs...
  :-   e#   Compute the difference between the two letters.
  g    e#   Signum. Gives -1 for rises, 1 for falls, 0 otherwise.
  )    e#   Increment. Gives 0 for rises, 2 for falls, 1 otherwise. Call this i.
  S3*  e#   Push a string with three spaces.
  0t   e#   Replace the i'th space (zero-based) with a zero.
}%
z      e# Transpose.
N*     e# Join with linefeeds.

6

Python 2, 76 71 bytes

lambda s:[''.join(' o'[cmp(*x)==n]for x in zip(s,s[1:]))for n in-1,0,1]

Agradeço ao @xnor por me notificar que é permitido retornar uma lista de strings.

Teste em Ideone .


Você tem permissão para gerar uma lista de três strings, o que permite fazer a lambda.
Xnor

Eu sou? Isso muda tudo.
Dennis

Eu perguntei nos comentários porque a resposta Haskell de Lynn estava fazendo isso.
xnor

6

JavaScript (ES6), 96 95 89 87 82 bytes

2 bytes salvos usando em 0vez de o, como sugerido por Conor O'Brien
2 6 bytes salvos graças a ETHproductions

let f =

s=>[1,0,-1].map(k=>s.replace(/./g,(c,i)=>i--?(c>s[i])-(c<s[i])-k&&' ':'')).join`
`

console.log(f("HELLOWORLD"));
console.log(f("EXAMINATION"));


1
Como você pode usar qualquer caractere, substituir 'o'por 0alguma ajuda?
Conor O'Brien

@ ConorO'Brien - De fato, ele faz. ;)
Arnauld 25/09

1
Eu acho que s=>[1,0,-1].map(k=>[...s].map(c=>(r=p?(c>p)-(c<p)-k&&' ':'',p=c,r),p=0).join``).join`\n` iria funcionar, economizando 2 bytes.
ETHproductions

Você pode salvar outro byte, agarrando o caractere anterior de cada vez, em vez de manualmente manter o controle do mesmo: s=>[1,0,-1].map(k=>[...s].map((c,i)=>(p=s[i-1])?(c>p)-(c<p)-k&&' ':'').join``).join`\n` . s.replacevocê também economizará vários bytes [...s].map().join().
ETHproductions

4

Perl, 47 bytes

Inclui +1 para -p

Dê entrada no STDIN:

bumpy.pl <<< ABBCBA

bumpy.pl:

#!/usr/bin/perl -p
$_ x=3;s%.%/\G(.)(.)/?$2cmp$1^$.&&$":--$.>0%eg

4

MATL, 16 14 bytes

dZSqq_tn:79Z?c

Experimente online!

Isso surgiu de uma discussão sobre a resposta do DJMCMahem . Embora essa resposta tenha dois caracteres com o mesmo tamanho, o método é um pouco diferente, portanto pode ser de interesse independente.

Agradecemos a Luis Mendo por uma sugestão de salvar 2 bytes (ver comentários)

Explicação:

'dZS' obtém um vetor em que cada entrada é o sinal das diferenças entre caracteres sucessivos, então 'qq_' diminui cada entrada em dois e vira o sinal; agora, se o caractere aumentar, será 1, se permanecer o mesmo 2, e se diminuir 3. Por exemplo,

dZSqq_ applied to 'HELLOWORLD' creates the vector [3 1 2 1 1 3 1 3 3]

Em seguida, 't' faz uma cópia do vetor anterior na pilha e, em seguida, 'n:' coloca o vetor [1,2,3,4, ...] na pilha também. Então '79' coloca o valor 79 na pilha. O valor 79 é escolhido porque é o número do caractere unicode 'o', que será a nossa saída mais tarde. (Obrigado a Luis Mendo pela idéia de colocar o valor 79 aqui em vez de mais tarde)

tn:79 applied to [3 1 2 1 1 3 1 3 3] creates the following items:
[3 1 2 1 1 3 1 3 3]   <-- first item on the stack
[1 2 3 4 5 6 7 8 9]   <-- second item on the stack
79                    <-- third item on the stack

Nesse ponto, temos precisamente os índices de linha, índices de coluna e valor diferente de zero de uma matriz esparsa que tem o valor 79 onde quer que desejemos o caractere de saída e 0 onde quer que deseje produzir espaço em branco. Retiramos esses três itens da pilha e criamos essa matriz esparsa com o comando de matriz esparsa do MATL 'Z?'. Isso é,

dZSqq_tn:79 Z? applied to 'HELLOWORLD' outputs the following:
[0  79 0  79 79 0  79 0  0 ]
[0  0  79 0  0  0  0  0  0 ]   <-- 3-by-n sparse matrix
[79 0  0  0  0  79 0  79 79]

Tudo o que resta é converter a matriz de números em caracteres unicode, o que é feito pelo comando 'c'. Os 79 se tornam 'o' e os 0 se tornam espaços:

dZSqq_tn:79Z?c applied to 'HELLOWORLD' outputs:
[  o   o o   o    ]
[    o            ]   <-- 3-by-n sparse matrix of characters.
[o         o   o o]

A matriz resultante de caracteres é exibida implicitamente.


Você pode usar diretamente 79 como o valor diferente de zero para a matriz esparsa, economizando dois bytes. Além disso, eu acho que esta é a primeira vez que matrizes esparsas são usados em uma resposta MATL :-)
Luis Mendo

@LuisMendo Thanks! Eu editei o post para fazer a alteração que você sugere #
Nick Alger

3

PHP, 95 bytes

for($b[1]=$b[0]=$b[-1]=" ";($s=$argv[1])[++$i];)$b[$s[$i-1]<=>$s[$i]][$i]=8;echo join("\n",$b);

1.Crie uma matriz de strings com o índice -1 a 1 alternativo $b=array_fill(-1,3," ");

2. Preencha as cordas dependentes do operador da nave espacial e a posição da entrada

3.Output juntar a matriz com uma nova linha

Primeira maneira 111 bytes

for($o=" ";$i<$l=strlen($s=$argv[1])-1;)$o[$l*(1+($s[$i]<=>$s[$i+1]))+$i++]=8;echo join("\n",str_split($o,$l));

Use o operador de nave espacial operador de <=> nave espacial


1
Se você codificar seu programa em latim-1 , é um atalho útil para "\n". Não, sério!
Lynn

1
A mesma coisa para " ", o que pode ser . Exemplo. Você deseja definir a codificação do navegador como Latin-1 ao visualizá-las.
Lynn

@Lynn ou ~ ³ ~ † ~ '~' Obrigado pela ideia. Eu prefiro o Unicode
Jörg Hülsermann

2

JavaScript (ES6), 81 bytes

s=>[s,s,s].map(f=([c,...s],n)=>(p=s[0])?((c<p)-(c>p)+n-1&&" ")+f(s,n):"").join`
`

Escrito do zero, embora tenha sido fortemente inspirado pela resposta de @ Arnauld . Usa recursão para calcular o conteúdo de cada linha.



2

Java 7, 158 156 bytes

String c(char[]z){String a,b,c=a=b="";for(char i=1,q=z[0],o=79,s=32,x;i<z.length;a+=(x=z[i])>q?o:s,b+=x==q?o:s,c+=x<q?o:s,q=z[i++]);return a+"\n"+b+"\n"+c;}

2 bytes salvos graças a @Frozn .

Casos não testados e de teste:

Experimente aqui.

class M{
  static String c(char[] z){
    String a,
           b,
           c = a = b = "";
    for(char i = 1,
             q = z[0],
             o = 79,
             s = 32,
             x; i < z.length; a += (x = z[i]) > q
                                     ? o
                                     : s,
                              b += x == q
                                     ? o
                                     : s,
                              c += x < q
                                     ? o
                                     : s,
                              q = z[i++]);
    return a + "\n" + b + "\n" + c;
  }

  public static void main(String[] a){
    print("HELLOWORLD");
    print("TESTCASE");
    print("EXAMINATION");
    print("ZSILENTYOUTH");
    print("ABC");
    print("ABCBA");
    print("ABBCBA");
    print("UVVWVVUVVWVVUVVW");
  }

  static void print(String s){
    System.out.println(c(s.toCharArray()));
    System.out.println("-------------------------");
  }
}

Saída:

 O OO O  
  O      
O    O OO
-------------------------
 OO  O 

O  OO O
-------------------------
O O O O O 

 O O O O O
-------------------------
  O OOO O  

OO O   O OO
-------------------------
OO


-------------------------
OO  

  OO
-------------------------
O O  
 O   
   OO
-------------------------
O O   O O   O O
 O  O  O  O  O 
   O O   O O   
-------------------------

1
Não tenho certeza se isso funciona, mas a,b,c=b=a=""seria mais curto.
Frozn 26/09/16

@Frozn Obrigado, editado. De fato funciona. PS: você poderia ter se chocado com o ideone, bifurcando-o. ;)
Kevin Cruijssen

Você está certo! Estou sempre com vista para as ligações e arranque eclipse só por isso não vale a pena :)
Frozn

2

Clora (20 bytes)

<IN?o ;=IN?o ;>IN?o

Explicação:

Existem 3 programas Clora, um para cada linha de saída.

Primeiro programa, <IN?o

Verifique se o caractere de entrada atual Ié menor <que o próximo caractere N. Salve o resultado em um sinalizador global. Verifique o resultado do sinalizador ?e, se for verdadeiro, produza o, ou então um espaço em branco (sim, existe um espaço em branco lá.

Todos os outros programas seguem a mesma regra e são separados por ;, todo programa é executado e recebe a entrada como argumento.

Você pode testá-lo sozinho, incluindo clora.js e executá-lo com

(function() {
  var x = new Clora('<IN?o ;=IN?o ;>IN?o ');
  x.execute('EXAMINATION', function(r) {
    console.log(r)
  })
})();

Isso parece ser estritamente não competitivo, pois foi criado após esse desafio. Parece um lang interessante!
Conor O'Brien

1

Pitão, 21 bytes

jCmX*3\ h._d0-M.:CMz2

Um programa que recebe a entrada de uma sequência não citada em STDIN e imprime o resultado.

Isso usa uma idéia semelhante à resposta CJam do @ MartinEnder .

Experimente online ou Verifique todos os casos de teste .

Como funciona

jCmX*3\ h._d0-M.:CMz2  Program. Input: z
                 CMz   Map ordinal over z, yielding the code-points of the characters
               .:   2  Yield all length-2 sublists of that
             -M        Map subtraction over that
  m                    Map the following over that with variable d:
         ._d            Yield the sign of d
        h               Increment that (i)
    *3\                 Yield string literal of 3 spaces, "   "
   X        0           Replace the space at index i with 0
 C                     Transpose that
j                      Join that on newlines
                       Implicitly print

1

PHP 7, 81 80 77 bytes

Nota: usa codificação Windows-1252

for($x=2;~$x--;print~õ)for($a=$argn;$c=$a[$$x+1];)echo$c<=>$a[$$x++]^$x?~ß:o;

Execute assim:

echo HELLOWORLD | php -nR 'for($x=2;~$x--;print"\n")for($a=$argn;$c=$a[$$x+1];)echo$c<=>$a[$$x++]^$x?" ":o;';echo

Explicação

Itera sobre linhas (numeradas 1, 0, -1). Em seguida, itera sobre a sequência de entrada para cada linha. Quando o resultado da comparação da nave espacial for igual ao número da linha, emita umo , caso contrário, faça a saída de um espaço. Após cada linha, imprima uma nova linha.

Tweaks

  • Pare de iterar quando $xé -1, o que podemos encontrar por negação binária (resultado 0). Salva um byte comparado à adição1 (ou 2 com pré-incremento).
  • Salva 3 bytes usando $argn

1
Você esqueceu de adicionar -d error_reporting=30709à sua contagem de bytes.
Titus

@Titus Por que no mundo eu precisaria adicionar isso à contagem de bytes? É apenas para que os avisos do PHP (que são ignoráveis) não sejam impressos!
aross 27/09/16

Também pode adicionar 2>/dev/null, mas que vai se livrar de erros de todos, inclusive fatal
aross


Algo como If you get warnings, set the default value with .... Por favor, desculpe meu pedantério; Eu não decodifiquei esse valor.
Titus

0

Lua 326 303 bytes tl = 0 s = io.read () o1, o2, o3 = "", "", "" t = {} para i = 1, # s faça t [i] = s: sub (i , i) tl = tl + 1 final para v = 1, tl-1 faz se t [v] t [v + 1] então o1 = o1 .. "" o2 = o2 .. "" o3 = o3 .. " o "impressão final final (o1 .." \ n ".. o2 .." \ n ".. o3)

Uma versão não destruída

tl = 0 --set the tables length to 0
s = io.read() --Get the string from input
o1,o2,o3="","","" --Set the 3 output rows to empty strings
t = {} --Make a table for the string to be sent into
for i = 1, #s do --Loop from 1 to the length of the string
    t[i] = s:sub(i, i) --Set the I-th term in the table to the I-th character in the string
    tl = tl+1 --Add 1 to the table length
end --End the loop
for v=1,tl-1, 1 do --Loop from 1 to the tables length - 1, incrementing by 1
    if t[v] < t[v+1] then --Lua supports greater than less than and equals to with charactes, so this if statement detects if the string is rising
        o1=o1.."o" --Adds an o to the end of the first line of output
        o2=o2.." " --Adds a space to the second line
        o3=o3.." " --Adds a space to the third line
    elseif t[v] == t[v+1] then --Detects if the string is continuing
        o1=o1.." " --Adds a space to the first line
        o2=o2.."o" --Adds an o to the second line
        o3=o3.." " --Adds a space to the third line
    elseif t[v] > t[v+1] then --Detects if string is falling
        o1=o1.." " --Adds a space to the first line
        o2=o2.." " --Adds a space to the second line
        o3=o3.."o" --Adds an o to the third line
    end --Ends the if statement
end --Ends the loop
print(o1.."\n"..o2.."\n"..o3) --Prints the output

Eu acho que você pode jogar fora de algum espaço em branco, digamos t1 = 0,? para t1=0? E lugares semelhantes.
Conor O'Brien

Vou resolver isso agora #
Alex Allen

0

R, 114 bytes

Uma resposta R não concorrente.

v=y=z=rep(" ",length(x<-diff(utf8ToInt(scan(,"")))));v[x>0]="#";y[x==0]="#";z[x<0]="#";cat(v,"\n",y,"\n",z,sep="")

Explicação

  1. Leia a entrada da linha de comando e converta em vetor decimal ascii
  2. Faça a 1ª diferença e crie 3x vetores do mesmo comprimento com espaços em branco
  3. Em seguida, substitua os vetores de espaço em branco por #se as diferenças forem >0, ==0ou <0.
  4. Coerce os vetores e imprima-os separados por novas linhas

Por que não competir?
Conor O'Brien

@ ConorO'Brien Acho que está competindo com outras respostas R, mas a solução original foi longa demais e não é única o suficiente para ser interessante no sentido geral.
Billywob 27/09/16
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.