Transforme lentamente uma corda em outra


31

O desafio

Dadas duas cadeias / uma matriz de cadeias, produza a primeira cadeia diminuindo lentamente e expandindo de volta para a segunda cadeia.

Você pode assumir que as strings sempre começarão com o mesmo caractere.

Exemplo

Input:
"Test", "Testing"

Output:
Test
Tes
Te
T
Te
Tes
Test
Testi
Testin
Testing

Primeiro você produz a primeira palavra:

Test

Então você continua removendo uma letra até que a cadeia tenha um caractere:

Tes
Te
T

Continue adicionando uma letra da segunda palavra até terminar:

Te
Tes
Test
Testi
Testin
Testing

(se as duas strings tiverem um caractere, basta imprimir uma delas uma vez.)

Casos de teste

"Hello!", "Hi."
Hello!
Hello
Hell
Hel
He
H
Hi
Hi.

"O", "O"

O

"z", "zz"

z
zz

".vimrc", ".minecraft"

.vimrc
.vimr
.vim
.vi
.v
.
.m
.mi
.min
.mine
.minec
.minecr
.minecra
.minecraf
.minecraft

"     ", "   "

SSSSS
SSSS
SSS
SS
S
SS
SSS

"0123456789", "02468"

0123456789
012345678
01234567
0123456
012345
01234
0123
012
01
0
02
024
0246
02468

(nota: no espaço / quarto caso de teste, substitua S por espaços)

Regras

  • Isso é , então a resposta mais curta em bytes vence! O desempate é o post mais votado. O vencedor será escolhido em 10/09/2016.

  • As brechas padrão são proibidas.


2 novas linhas à direita (uma linha vazia visível após a sequência) serão permitidas ou não?
seshoumara

Respostas:


11

Pitão, 9 bytes

j+_._Et._

Um programa que pega a segunda cadeia e, em seguida, a primeira, como cadeias citadas em STDIN e imprime o resultado.

Experimente online

Como funciona

j+_._Et._  Program. Inputs: Q, E
   ._E     Yield prefixes of E as a list
  _        Reverse the above
       ._  Yield prefixes of Q as a list (implicit input fill)
      t    All but the first element of above
 +         Merge the two lists
j          Join on newlines
           Implicitly print

14

V , 14 bytes

òYp$xhòjòÄ$xhh

Experimente online!

Explicação:

ò     ò     "Recursively:
 Yp         "  Yank the current line and paste it
   $        "  Move to the end of the current line
    x       "  Delete one character
     h      "  Move One character to the right.
            "  Because of the way loops work in V, this will throw an error if there
            "  Is only one character on the current line.

Agora, o buffer fica assim:

0123456789
012345678
01234567
0123456
012345
01234
0123
012
01
0

Só precisamos fazer a mesma coisa ao contrário para a próxima linha:

j           "Move down one line
 ò     ò    "Recursively (The second ò is implicit)
  Ä         "  Duplicate this line up
   $        "  Move to the end of the current line
    x       "  Delete one character
     hh     "  Move two characters to the right.
            "  Because of the way loops work in V, this will throw an error if there
            "  Is only two characters on the current line.

Solução alternativa mais interessante :

òÄ$xhòç^/:m0
ddGp@qd

3
É como vim é sempre ferramenta correta para o trabalho
Downgoat

@Downgoat Exatamente. É por isso que você precisa começar a jogar golfe em V.: P
DJMcMayhem

9

Python, 93 bytes

f=lambda a,b,r='',i=2:a and f(a[:-1],b,r+a+'\n')or(len(b)>=i and f(a,b,r+b[:i]+'\n',i+1)or r)

Começa com a sequência vazia r, adiciona ae uma nova linha e remove o último caractere de aaté que aesteja vazio, em seguida, adiciona as partes necessárias be uma nova linha mantendo um contador i, que começa em 2até que o comprimento bseja excedido e retorna r. Tem uma nova linha à direita.

Todos os testes são em ideone


2 coisas. 1) Acredito que você tenha contado mal os personagens e na verdade são 93 e 2) Você não precisa dizer r="". Simples rainda funcionaria.

Obrigado @JackBates. 1. Correto e atualizado - eu provavelmente esqueci o f=. 2. Sem o r=''presente f('test','testing')não funcionaria; sim f('test','testing',''), mas devemos seguir as especificações.
Jonathan Allan

Me perdoe. Eu estava apenas olhando o código e não os exemplos.

7

05AB1E , 9 bytes

.pRI.p¦«»

Explicação

.pR           # prefixes of first word
     I.p       # prefixes of second word
         ¦       # remove first prefix
          «     # concatenate
           »    # join with newlines

Experimente online!


7

Retina, 50 41 26 bytes

Agradecemos a Martin Ender por salvar 15 (!) Bytes.

M&!r`.+
Om`^.¶[^·]+|.+
A1`

Recebe entrada com as duas cadeias separadas por uma nova linha:

Test
Testing

Experimente online!

Explicação

M&!r`.+

A primeira linha gera os "passos" de ambas as palavras:

Testing
Testin
Testi
Test
Tes
Te
T
Test
Tes
Te
T

Mé para o modo de correspondência, &considera correspondências sobrepostas e !imprime as correspondências em vez do número delas. A razão pela qual é revertida é a ropção da direita para a esquerda: o mecanismo começa a procurar correspondências no final da sequência e continua em direção ao início.

Om`^.¶[^·]+|.+

Isso coloca tudo na ordem certa: ele Oreproduz todas as correspondências da regex subseqüente: um caractere em sua própria linha e cada caractere (incluindo novas linhas) depois dele, que corresponde a toda a segunda metade como um pedaço ou uma linha de caracteres , que corresponde a cada linha individual. Essas correspondências são classificadas por ponto de código, para que o T seguido pela nova linha vá primeiro, seguido pelas linhas, ascendendo pelo comprimento.

A1`

Agora, temos apenas a primeira linha de caracteres no topo, portanto, usamos o Amodo ntigrep para descartar a primeira correspondência da regex padrão .+.

Versão antiga

M&!r`.+
O`\G..+¶
s`(.*)¶.¶(.*)
$2¶$1
¶.$

Experimente esta versão online!

Explicação

A primeira linha é a mesma, então veja a explicação para isso acima.

O`\G..+¶

Isso inverte as linhas da primeira metade (segunda palavra de entrada). Na verdade, ele Odefine as linhas e a expressão regular limita as correspondências: deve ser uma linha de dois ou mais caracteres ( ..+) seguida por uma nova linha ( ) que começa onde o último parou ( \G). No exemplo acima, o single Tno meio não corresponde, então nada depois pode.

Te
Tes
Test
Testi
Testin
Testing
T
Test
Tes
Te
T

Agora, temos os dois componentes certos, mas na ordem errada.

s`(.*)¶.¶(.*)
$2¶$1

¶.¶corresponde ao T solitário no meio, do qual não precisamos, mas separa as duas partes. Os dois (.*)capturam tudo antes e depois, incluindo novas linhas graças ao modo single-line. As duas capturas são substituídas na ordem correta por uma nova linha no meio.

Agora terminamos, a menos que as seqüências de entrada tenham um caractere, nesse caso, a entrada não mudou. Para se livrar da duplicata, substituímos ¶.$(quando a última linha da string um único caractere) por nada.


4

Python 2, 88 82 bytes

x,y=input(),input()
for i in x:print x;x=x[:-1]
s=y[0]
for i in y[1:]:s+=i;print s

Toma duas entradas, cada uma entre aspas.

Obrigado @ JonathanAllan por salvar alguns bytes e apontar um erro.


1
Não há necessidade de entrada len(x), x=x[:len(x)-1]já que a fatia de deslocamento negativo funciona - basta escrever x=x[:-1]. O único problema é que seu código não processará " ", " "muito bem o caso de teste.
Jonathan Allan

1
Você pode soltar o segundo input()e usar um formato de entrada como"<str1>", "<str2>"
LevitatingLion

Você pode alterar a segunda linha para for i in range(x):print x[-i:]e a quarta linha para for i in range(1,y):print y[:-i]. Não tenho certeza se funcionaria.
Clismique

4

Perl, 34 28 bytes

Inclui +2para-0n

Execute com as strings em linhas separadas no STDIN:

perl -M5.010 -0n slow.pl
Test
Testing
^D

slow.pl:

/(^..+|
\K.+?)(?{say$&})^/

Deixe o regex voltar ao trabalho ...



3

Braquilog , 32 bytes

:1aLtT,Lhbr:Tc~@nw
:2fb
~c[A:B]h

Experimente online!

Explicação

O Brachylog não possui prefixo embutido, portanto, obteremos os prefixos usando concatenate(Veja o predicado 2): um prefixo de Sé Pse Pconcatenado para Q(o que quer que seja) resultar S.

  • Predicado principal:

    :1aL                  L is all prefixes of both elements of the input (see predicate 1)
       LtT,               T is the second element of L
           Lhbr           Remove the first prefix of the first list of L and reverse it
               :Tc        Concatenate with T
                  ~@n     Join with newlines
                     w    Write to STDOUT
    
  • Predicado 1:

    :2f                   Find all prefixes of the input string (see predicate 2)
       b                  Remove the first one (empty string)
    
  • Predicado 2:

    ~c[A:B]               Input is the result of concatenating A to B
           h              Output is A
    

3

Javascript, 103 81 bytes

f=(x,y,n=1)=>x?`
`+x+f(x.slice(0,-1),y):n++<y.length?`
`+y.slice(0,n)+f(x,y,n):''

Exemplo: f("Test", "Testing")

Saída:

Test
Tes
Te
T
Te
Tes
Test
Testi
Testin
Testing

Resposta original

f=(x,y,n=1)=>x?(console.log(x),f(x.slice(0,-1),y)):n++<y.length?(console.log(y.slice(0,n)),f(x,y,n)):''

3

Java, 188 179 bytes

interface E{static void main(String[]a){int i=a[0].length();while(i>1)System.out.println(a[0].substring(0,i--));while(i<=a[1].length())System.out.println(a[1].substring(0,i++));}}

Atualizar

  • Variável removida, salva 9 bytes

Ungolfed :

interface E {

    static void main(String[] a) {
        int i = a[0].length();
        while (i > 1) {
            System.out.println(a[0].substring(0, i--));
        }
        while (i <= a[1].length()) {
            System.out.println(a[1].substring(0, i++));
        }
    }
}

Uso :

$ java E 'test' 'testing'
test
tes
te
t
te
tes
test
testi
testin
testing

3

Haskell, 54 53 47 bytes

t[]=[]
t x=x:t(init x)
(.reverse.t).(++).init.t

Exemplo de uso: ((.reverse.t).(++).init.t) "Hello" "Hi!"-> ["Hello","Hell","Hel","He","H","Hi","Hi!"].

Um pouco de mágica sem sentido. É o mesmo que f x y = (init(t x))++reverse (t y)where tfaz uma lista de todas as substrings iniciais, por exemplo t "HI!"- -> ["H","HI","HI!"].


Hum t=reverse.tail.inits?
Bergi 5/09/16

@ Bergi: claro, mas initsprecisa import Data.List.
nimi


3

GNU sed, 57 45 + 2 (sinalizadores de rn) = 47 bytes

:;1{/../p};2G;2h;s/.(\n.*)?$//;/./t;g;s/.$//p

Corre:

echo -e "Test\nTesting" | sed -rnf morphing_string.sed

A entrada deve ser as duas cadeias separadas por uma nova linha. O código é executado pelo sed para cada linha.

O loop :exclui um caractere do final da string de forma iterativa. A saída relacionada com a primeira corda é impresso diretamente, exceto o primeiro caractere: 1{/../p}. A saída da segunda sequência é armazenada no espaço de espera na ordem inversa ( 2G;2h) durante a exclusão e impressa no final.


3

C (gcc) , 102 97 95 93 bytes

n;f(char*a,char*b){for(n=strlen(a);n;puts(a))a[n--]=0;for(a=b+1;*a++;*a=n)n=*a,*a=0,puts(b);}

Experimente online!

O primeiro loop sobrescreve a string com 0 bytes a partir do final e usa puts() para imprimir a sequência. O segundo loop não pode simplesmente sobrescrever desde o início, ele precisa armazenar o valor antigo para poder recuperá-lo; o byte 0 está apenas caminhando para o final.

Obrigado a @homersimpson e @ceilingcat por cada remoção de 2 bytes!


1
Você pode salvar um par de bytes, declarando ncomo um int global como: n;f(char*a,char*b){n=strlen(a).... E você provavelmente pode fazer n=*a=0como uma tarefa encadeada no corpo do seu loop for.
Homer Simpson

Obrigado @homersimpson. Mas n = * a = 0 não é o mesmo que n = * a, * a = 0.
G. Sliepen 8/09/16

2

Python 3, 104 bytes

Meh.

n='\n';lambda x,y:x+n+n.join(x[:-i]for i in range(1,len(x)-1))+n+n.join(y[:i]for i in range(1,len(y)+1))

Graças a @DJMcMayhem por jogar 21 bytes de desconto.

Ideone it!


1
Você pode n='\n'usar 5 bytes se fizer isso e usar n em vez de '\n'. Você poderia ter um outro 8 off se você usou um lambda em vez de imprimir:n='\n';lambda x,y:n.join(x+n+n.join(x[:-i]for i in range(1,len(x)-1))+n+n.join(y[:i]for i in range(1,len(y)+1)))
DJMcMayhem

2

REPL / Javascript, 109 bytes

Usa string falsa para diminuir a string original

Abusa de substring com números maiores para aumentar o segundo, para quando está prestes a imprimir a mesma palavra da última vez.

(a,b)=>{l=console.log;z='substring';for(c=a.length;d=a[z](0,c--);){l(d)}for(c=2;d!=(n=b[z](0,c++));){l(d=n)}}

Demo:

> ((a,b)=>{l=console.log;z='substring';for(c=a.length;d=a[z](0,c--);){l(d)}for(c=2;d!=(n=b[z](0,c++));){l(d=n)}})("asdf","abcd")
[Log] asdf
[Log] asd
[Log] as
[Log] a
[Log] ab
[Log] abc
[Log] abcd

1
é um byte mais curto para fazer a=>b=>...e chamar a função de (a), (b)
Zwei

2

Brainfuck, 38 55 bytes

>++++++++++>,[>,]<[<]>>[[.>]<[-]<[<]>.>],.[[<]>.>[.>],]

Editar: novas linhas incluídas na saída


Não consigo fazer seu código funcionar. A entrada está separada por uma nova linha? Qual intérprete você está usando?
acrolith 9/09/16

2

Dyalog APL , 20 13 bytes

↑(⌽,\⍞),1↓,\⍞

matrificar

(⌽,\⍞)concatenação cumulativa reversa ( ) (,\ ) da entrada de caracteres ( )

, anexado a

1↓ um elemento caiu de

,\⍞ concatenação cumulativa da entrada de caracteres

TryAPL online!


2

Raquete 193 bytes

(define(f l)
(let*((s(list-ref l 0))
(x(string-length s)))
(for((n x))
(println(substring s 0(- x n))))
(set! s(list-ref l 1))
(for((n(range 1(string-length s))))
(println(substring s 0(add1 n))))))

Teste:

(f(list "Test" "Testing"))

"Test"
"Tes"
"Te"
"T"
"Te"
"Tes"
"Test"
"Testi"
"Testin"
"Testing"


(f(list "Hello!" "Hi."))

"Hello!"
"Hello"
"Hell"
"Hel"
"He"
"H"
"Hi"
"Hi."

Ele deve excluir o último caractere da sequência de entrada, não o primeiro.
agilob

2

Floróide , 69 bytes

a,b=L.J
c=1
NZ(a)!=1:z(a);a=a[:-1]
z(a)
NZ(a)!=Z(b):c+=1;a=b[:c];z(a)

É um começo. Toma a entrada de STDIN.

Casos de teste

Input: Test Testing
Output:
Test
Tes
Te
T
Te
Tes
Test
Testi
Testin
Testing

Input: O O
Output: O

1

JavaScript (ES6), 92 bytes

(s,t)=>s.replace(/./g,`
$\`$&`).split`
`.slice(2).reverse().join`
`+t.replace(/./g,`
$\`$&`)

o replace instruções constroem um triângulo de strings, exatamente o que é necessário para a segunda metade da saída, no entanto, a primeira metade precisa ser revertida e a linha de um único caractere duplicada removida. Nota: gera uma nova linha inicial se a primeira sequência for um único caractere. Se isso for indesejável, para um byte extra, esta versão sempre gera uma nova linha à direita:

(s,t)=>s.replace(/./g,`
$\`$&\n`).split(/^/m).slice(1).reverse().join``+t.replace(/./g,`
$\`$&\n`)

1

C, 142 bytes

#define _(x,y) while(y)printf("%.*s\n",d,x-c);
f(char*a,char*b){int c=1,d=strlen(a)+1;while(*++a==*++b)c++;_(a,--d>=c)d++;_(b,d++<strlen(b-c))}

Forneça f(char* str1, char* str2).


1

TI-Basic, 56 bytes

Prompt Str1,Str2
Str1
While 1<length(Ans
Disp Ans
sub(Ans,1,length(Ans)-1
End
For(I,1,length(Str2
Disp sub(Str2,1,I
End

Exemplo de uso

Str1=?Test
Str2=?Testing
Test
Tes
Te
T
Te
Tes
Test
Testi
Testin
Testing

Str1=?O
Str2=?O
O

Str1=?z
Str2=?zz
z
zz

1

Java, 168 136 bytes

(s,d)->{int i=s.length()+1;while(i-->1)System.out.println(s.substring(0,i));while(i++<d.length())System.out.println(d.substring(0,i));};

Programa de teste ungolfed

public static void main(String[] args) {

    BiConsumer<String, String> biconsumer = (s, d) -> {
        int i = s.length() + 1;
        while (i-- > 1) {
            System.out.println(s.substring(0, i));
        }
        while (i++ < d.length()) {
            System.out.println(d.substring(0, i));
        }
    };

    biconsumer.accept("Test", "Testing123");

}

1

(Lambdabot) Haskell - 41 bytes

f=(.drop 2.inits).(++).reverse.tail.inits

Mais legível, mas com mais dois bytes:

a!b=(reverse.tail$inits a)++drop 2(inits b)


Saída:

f "Hello" "Hi!"
["Hello","Hell","Hel","He","H","Hi","Hi!"]

1

J, 18 bytes

]\@],~[:}:[:|.]\@[

Ungolfed:

]\@] ,~ [: }: [: |. ]\@[

Este é um trem de 7:

]\@] ,~ ([: }: ([: |. ]\@[))

O trem mais interno [: |. ]\@[consiste em um limite [:à esquerda, então aplicamos |.(reverso) ao resultado de ]\@[, que é ]\(prefixos) sobre[ (argumento à esquerda).

Aqui está o que parece na testing, testentrada:

   'testing' ([: |. ]\@]) 'test'
test
tes
te
t

Isso nos dá a primeira parte, quase. O trem 5 fora disso é ([: }: ([: |. ]\@[)), que se aplica }:(betail, remove last element) à expressão acima:

   'testing' ([: }: [: |. ]\@]) 'test'
test
tes
te

(Isso ocorre porque não podemos ter um ponto médio duplicado.)

A parte externa é finalmente:

]\@] ,~ ([: }: ([: |. ]\@[))

Isso é composto por ]\@](prefixos de argumento à esquerda) e ,~(acrescenta o que está à esquerda com o que está à direita), deixando-nos com o resultado desejado:

   'testing' (]\@] ,~ ([: }: ([: |. ]\@[))) 'test'
testing
testin
testi
test
tes
te
t
te
tes
test

Casos de teste

   k =: ]\@] ,~ ([: }: ([: |. ]\@[))
   'o' k 'o'
o
   k~ 'o'
o
   'test' k 'test'
test
tes
te
t
te
tes
test
   k~ 'test'
test
tes
te
t
te
tes
test
   '. . .' k '...'
. . .
. .
. .
.
.
..
...
   'z' k 'zz'
z
zz

Você pode reorganizá-lo para 14 bytes usando(,~}:@|.)&(]\)
miles

1

PHP, 117 109 bytes

for($i=strlen($a=$argv[1]);$i>1;)echo" ".substr($a,0,$i--);
for(;$j<strlen($b=$argv[2]);)echo" ".$c.=$b[$j++];

for($i=strlen($a=$argv[1]);$i>1;)echo substr($a,0,$i--)." ";
for(;$i<=strlen($b=$argv[2]);)echo substr($b,0,$i++)." ";

PHP, 107 bytes (não funciona com cadeias de caracteres 0)

for($a=$argv[1];$a[$i];)echo substr($a.a,0,-++$i)." ";
for($b=$argv[2];$b[$j];)echo substr($b,0,++$j+1)." ";

1

C, 111 bytes

f(char*a, char*b){int l=strlen(a),k=1;while(*a){printf("%s\n",a);a[--l]=0;}while(b[k]) printf("%.*s\n",++k,b);}

Teste ungolfed

#include <stdio.h>
#include <string.h>

f(char*a, char*b) {
  int l=strlen(a), k=1;
  while(*a) {
    printf("%s\n",a);
    a[--l]=0;
  }
  while(b[k])
    printf("%.*s\n",++k,b);
}

int main() {
  char a[10] = {0};
  char b[10] = {0};

  for (int i=0; i<5; ++i) {
    a[i] = 'a' + i;
    b[i] = 'a' + i*2;
  }

  f(&(a[0]), &(b[0]));
}

1

brainfuck, 162 bytes

,[>,]++++++++++[[-<]>[->]<]++++++++++[<[+<]<[+<]>[+>]>[+>]<---]<[<]<[<]>[[.>]++++++++++.----------<[-]<[[->+<]<]>>]>[<+>-]>[[<+>-]<[<]>[.>]++++++++++.---------->]

Experimente aqui

A entrada pega as duas cadeias separadas por um avanço de linha.

Primeiro programa com brianfuck e primeiro código de golfe, então tenho certeza de que há muita otimização a ser feita. Diverti-me fazendo isso.

Ungolfed

,[>,] Read all input
++++++++++ Flag for 10
[                   Subtract 10 from each cell to flag space for blank
    [-<]            
    >
        [->]
        <
]
++++++++++ Flag for 10
[                   Add 10 back to each cell with value in it
    <[+<]<[+<]
    >[+>]>[+>]<---
]
<[<]<[<]>               goto first cell in first string string      

[                           Print first word subtracting one each time
    [.>]                    Print first string
    ++++++++++.----------   Print new line
    <[-]                    Kill last letter of first string
    <                       Back one
    [                       Move each first string character up one
          [->+<]
          <
    ]>>
]
>[<+>-]>                    Move to first letter of scond string back one goto second letter
[                               
    [<+>-]                  Move next letter back
    <[<]>                   Move to start of string
    [.>]                    Print string
    ++++++++++.----------   Print new line
    >
]

Bem-vindo ao PPCG! Primeiro post impressionante!
Rɪᴋᴇʀ
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.