Backspace-e-redigite uma lista de palavras

38

Veja como retroceder e digitar novamente de uma sequência para outra:

  1. Comece da primeira string.
  2. Remova os caracteres no final até o resultado ser um prefixo da segunda sequência. (Isso pode levar 0 etapas.)
  3. Adicione caracteres no final até que o resultado seja igual à segunda string. (Isso também pode levar 0 etapas.)

Por exemplo, o caminho de fooabcpara se fooxyzparece com:

fooabc
fooab
fooa
foo
foox
fooxy
fooxyz

Tarefa

Dada uma lista de palavras, escreva um programa que retroceda e retorne seu caminho da sequência vazia, para todas as palavras da lista em sucessão, de volta para a sequência vazia. Saída todas as seqüências intermediárias.

Por exemplo, dada a lista de entrada ["abc", "abd", "aefg", "h"], a saída deve ser:

a
ab
abc
ab
abd
ab
a
ae
aef
aefg
aef
ae
a

h

Regras

Você pode retornar ou imprimir uma lista de cadeias ou uma única cadeia com algum delimitador de sua escolha. Opcionalmente, você pode incluir as cadeias vazias inicial e final. É garantido que a entrada contenha pelo menos uma palavra e cada palavra contenha apenas letras ASCII em minúsculas ( a- z). Editar: seqüências consecutivas na entrada são garantidas para não serem iguais.

Isso é ; o menor código em bytes vence.

Uma implementação de referência no Python 3: Experimente online!

Lynn
fonte
4
@ rahnema1> escrever um programa que backspace-and-retypes seu caminho a partir do string vazia
Kritixi Lithos
3
Como seria a saída ["abc","abc"]?
Kritixi Lithos 15/01
1
@ Emigna Opa, é exatamente isso, mas em um loop! Então vou dizer que isso é uma duplicata.
Lynn
4
@ Lynn Não é exatamente a mesma coisa. Esse não inclui o reconhecimento dos prefixos comuns, mas sempre diminui para um caractere.
Martin Ender
6
Caso de teste:a,abc,abcde,abc,a,abc,abcde
Zgarb 15/01

Respostas:

9

Perl, 43 bytes

42 bytes de código + -nsinalizadores.

chop$@,say$@while!s/^$@//;s/./say$@.=$&/ge

Para executá-lo:

perl -nE 'chop$@,say$@while!s/^$@//;s/./say$@.=$&/ge' <<< "abc
abd
aefg
h"
dada
fonte
isso imprime abc 3 vezes
izabera 16/01/17
@izabera Houve um espaço depois de abcfazer com que fosse impresso 3 vezes (mas, na verdade, a primeira e a terceira vez foi sem espaço). Eu removi isso.
Dada
5

Java 8, 144 bytes

Este é semelhante à implementação de referência, mas combina os dois whileloops. É uma expressão lambda que aceita um String[]parâmetro.

a->{String c="";int l=0,i;for(String w:a)while((i=w.indexOf(c))!=0||!c.equals(w))System.out.println(c=i!=0?c.substring(0,--l):c+w.charAt(l++));}

Ungolfed

a -> {
    String c = "";
    int l = 0, i;
    for (String w : a)
        while ((i = w.indexOf(c)) != 0 || !c.equals(w))
            System.out.println(c = i != 0 ? c.substring(0, --l) : c + w.charAt(l++));
}

Agradecimentos

  • -38 bytes graças à sugestão lambda do CAD97
Jakob
fonte
Não é mais barato usar em class Bvez de interface B? Você pode executar a partir de uma classe privada de pacote. Além disso, considere usar um lambda como você já especificou o Java8.
CAD97
@ CAD97 interface B{static void mainé menor que class B{public static void main.
Kevin Cruijssen
@ CAD97 Não consegui pensar em uma maneira de trazer lambdas para isso, mas só aprendi sobre elas ontem. Alguma ideia?
Jakob
1
Ah, estou enferrujada. Você deve poder fazer isso a->{/*your code*/}, o qual será atribuído a uma variável do tipo java.util.function.Consumer<String[]>. Não posso testar no momento, no entanto.
97 de CAD16
1
@JakobCornell Por padrão, o PPCG permite envios completos de programas ou funções. Para idiomas com funções anônimas (lambda), a função anônima por si só é uma resposta aceitável (portanto, você não precisa incluir a variável para armazená-la). (Embora em envios de Java seja cortês fornecer o tipo de lambda.) #
9797
4

Mathematica, 149 bytes

Reap[Fold[n=NestWhile;s=StringMatchQ;r=StringReplace;n[k=#2;Sow@r[k,#~~a_~~___:>#<>a]&,n[Sow@r[#,a___~~_:>a]&,#,!s[k,#~~___]&],k!=#&]&,"",#]][[2,1]]&
JungHwan Min
fonte
3

Retina , 39 bytes

A contagem de bytes assume a codificação ISO 8859-1.

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

Experimente online!

Entrada e saída são listas separadas por avanço de linha. A saída inclui a sequência vazia inicial e final.

Martin Ender
fonte
3

Geléia , 31 29 26 bytes

⁷œ|;\
ÇṚðfḢṭḟ;ḟ@ḊðÇ}
⁷;ç2\

Experimente online!

Como funciona

⁷;ç2\           Main link. Argument: A (string array)

⁷;              Prepend a linefeed to A. 
                This is cheaper than prepending an empty string.
  ç2\           Reduce all overlapping pairs by the second helper link.


ÇṚðfḢṭḟ;ḟ@ḊðÇ}  Second helper link. Arguments: s, t (strings)

Ç               Call the first helper link with argument s.
 Ṛ              Reverse the results.
            Ç}  Call the first helper link with argument t.
  ð        ð    Combine everything in between into a dyadic chain, and call it
                with the results to both sides as arguments.
                Let's call the arguments S and T.
   f            Filter; get the common strings of S and T.
    Ḣ           Head; select the first one.
      ḟ         Filterfalse; get the strings in S that do not appear in T.
     ṭ          Tack; append the left result to the right one.
        ḟ@      Filterfalse swap; get the strings in T that do not appear in S.
       ;        Concatenate the results to both sides.
          Ḋ     Dequeue; remove the first string.


⁷œ|;\           First helper link. Argument: s (string)

⁷œ|             Linefeed multiset union; prepend a linefeed to s unless it already
                has a linefeed in it (the first string does).
   ;\           Concatenate cumulative reduce; generate all prefixes of the result.
Dennis
fonte
2

Haskell , 102 93 91 90 bytes

(?)=take.length
a!x@(b:c)|a==b=b!c|a/=a?b=a:init a!x|d<-'?':a=a:d?b!x
_!x=x
(""!).(++[""])

A última linha é uma função anônima, que pega e retorna uma lista de strings. Experimente online!

Explicação

Minha solução é recursiva. Primeiro, ?é uma função auxiliar de infixo: a?bfornece os primeiros length acaracteres de b, ou o conjunto de bse aé maior. Em seguida, defino uma função infix !. A idéia é que a!x, onde ahá uma string e xuma lista de strings, produza o caminho da aprimeira string xe volte ao final de x. Na linha final, defino uma função anônima que acrescenta a string vazia e depois se aplica !à string vazia e à entrada.

Explicação de !:

a!x@(b:c)        -- a!x, where x has head b and tail c:
  |a==b          -- If a equals b,
    =b!c         -- recurse to x.
  |a/=a?b        -- If a is not a prefix of b,
    =a:          -- produce a and
    init a!x     -- continue with one shorter prefix of a.
  |              -- Otherwise a is a proper prefix of b.
   d<-'?':a      -- Let d be a with an extra dummy element,
    =a:          -- produce a and
    d?b!x        -- continue with one longer prefix of b.
_!x=x            -- If x is empty, return x.
Zgarb
fonte
2

Python 2, 118 107 103 97 93 92 bytes

s=''
for i in input()+[s]:
 while i.find(s):s=s[:-1];print s
 while i>s:s+=i[len(s)];print s

A entrada é fornecida como ['abc', 'abcdef', 'abcfed'], ou como [ "abc", "abcdef", "abcfed"].

Revisão 1: -11 bytes. O crédito vai para @xnor por seu post sobre dicas de golfe em Python, e para @Lynn por encontrar a dica para mim e por ser inteligente. Duas alterações foram feitas: em vez de not s.startswith(i), eu usei s.find(i)e em vez de i!=seu usei i>s.

Revisão 2: -4 bytes. O crédito me ocorre ao perceber que cometi um erro muito estúpido. Em vez de usar o recuo de tabulação única e de tabulação dupla, usei o recuo de espaço único e de tabulação única.

Revisão 3: -6 bytes. O crédito vai para @ mbomb007 por sugerir colocar os whiles em uma única linha. Também corrigi um erro mudando s.find(i)para i.find(s).

Revisão 4: -4 bytes. O crédito vai para @xnor por perceber que eu não precisava armazenar a entrada em uma variável.

Revisão 5: -1 byte. O crédito é para mim por perceber que ['']é a mesma coisa que [s]ao adicioná-lo à entrada.

HyperNeutrino
fonte
Coloque os whiles em uma única linha. Além disso, você pode usar em <1vez de not.
mbomb007
Boa resposta! Há uma boa dica do xnor sobre como evitarstartswith .
Lynn
@ Lynn Oh, obrigado pelo link! Achei muito útil!
HyperNeutrino
@ mbomb007 Me desculpe, eu não entendi direito colocando os whiles em uma única linha. Você quer dizer como while s.find(i):s=s[:-1];print s? Além disso, obrigado pela sugestão <1, mas mudei para algo ainda mais curto, graças a uma das dicas do xnor no segmento de dicas do Python.
HyperNeutrino 18/01/19
@AlexL. Sim, por enquanto é assim.
mbomb007
1

GNU M4, 228 ou 232 bytes¹

(¹ dependendo de terminar dnl\nou não o arquivo - ainda sou novo no golfe e no M4)

define(E,`ifelse(index($2,$1),0,`T($1,$2)',`$1
E(substr($1,0,decr(len($1))),$2)')')define(T,`ifelse($1,$2,,`$1
T(substr($2,0,incr(len($1))),$2)')')define(K,`ifelse($2,,$1,`E($1,$2)K(shift($@))')')define(M,`K(substr($1,0,1),$@)')

Além disso, 3 bytes podem ser salvos substituindo o segundo argumento de substrfrom 0para a string vazia, mas isso produziria muitos avisos no stderr.

Ungolfed:

define(erase_til_prefix, `dnl arguments: src dst; prints src and chops one char off of it until src == dst, at which point it calls type_til_complete instead
ifelse(dnl
index($2, $1), 0, `type_til_complete($1, $2)',dnl
`$1
erase_til_prefix(substr($1, 0, decr(len($1))), $2)dnl
')')dnl
define(type_til_complete, `dnl arguments: src dst; types src, does not type `dst' itself
ifelse(dnl
$1, $2, ,dnl
`$1
type_til_complete(substr($2, 0, incr(len($1))), $2)'dnl
)')dnl
define(main_, `dnl
ifelse(dnl
$2, , $1, dnl no arguments left
`erase_til_prefix($1, $2)main_(shift($@))'dnl
)')dnl
define(main, `main_(substr($1, 0, 1), $@)')dnl

Uso:

$ m4 <<<"include(\`backspace-golfed.m4')M(abc, abd, aefg, abcdefg, h)"
Suspense
fonte
1

PHP, 116 111 101 83 bytes

Nota: usa a codificação Windows-1252.

for(;$w=$argv[++$i];)for(;$c!=$w;)echo$c=($c^$c^$w)==$c?$c.ÿ&$w:substr($c,0,-1),~õ;

Execute assim:

php -r 'for(;$w=$argv[++$i];)for(;$c!=$w;)echo$c=($c^$c^$w)==$c?$c.ÿ&$w:substr($c,0,-1),~õ;' -- abc abd aefg h 2>/dev/null
> a
> ab
> abc
> ab
> abd
> ab
> a
> ae
> aef
> aefg
> aef
> ae
> a
>
> h

Explicação

for(                       # Outer loop.
  ;
  $w=$argv[++$i];          # Loops over the input words.
)
  for(                     # Second inner loop.
    ;
    $c!=$w;                # Loop until the word was output.
  )
    echo $c=
      ($c^$c^$w)==$c?      # Check if last output string is a substring
                           # match with the next word to output.
        $c.ÿ&$w:           # ... If yes, suffix the string with the next
                           # char of the word, and output the result.
        substr($c,0,-1),   # ... If not, remove a char and output.
      ~õ;                  # Output newline.

Tweaks

  • Economizou 5 bytes usando trim($c^$w,"\0")para verificar a correspondência de substring em vez de $c&&strpos($w,$c)!==0.
  • Salva 2 bytes usando ~ÿpara gerar uma sequência com um byte NUL em vez de"\0"
  • Economizou 8 bytes usando o $c=$c.ÿ&$wsufixo $cno próximo caractere de$w
  • Economizou 18 bytes maciços combinando a lógica dos 2 loops internos em um único loop
  • Corrigido um erro com uma caixa de teste dos comentários, nenhuma alteração na contagem de bytes
aross
fonte
1

Lote, 296 291 bytes

@echo off
set f=
set t=%1
:t
set f=%f%%t:~,1%
set t=%t:~1%
echo(%f%
if not "%t%"=="" goto t
shift
set t=%1
set s=%f%
set p=
:h
if %s:~,1%==%t:~,1% set p=%p%%t:~,1%&set s=%s:~1%&set t=%t:~1%&goto h
:b
set f=%f:~,-1%
echo(%f%
if not "%f%"=="%p%" goto b
if not "%1"=="" goto t

Computar o prefixo comum era complicado.

Neil
fonte
0

PHP, 153 bytes

muito longo :(

for($s=$argv[$k=1];$t=$argv[++$k];){for(;$s>""&&strstr($t,$s)!=$t;$s=substr($s,0,-1))echo"$s
";for($i=strlen($s);$s<$t;$s.=$t[$i++])echo"$s
";echo"$s
";}

Corra com php -nr '<ode>' <text1> <text2> ....

Titus
fonte
0

JavaScript (ES6), 135 bytes

Desafio interessante! Uso: g(["abc", "abd", "aefg", "h"]). Não consegui salvar nenhum bytes escrevendo isso como uma função, então são dois. Novas linhas não incluídas na contagem de bytes.

f=a=>console.log(([,...z]=[x,y]=a)[0])||
y?f(a=(x==y.slice(0,-1))?z:([y.match(x)
?x+y[x.length]:x.slice(0,-1),...z])):1;
g=a=>f(['',...a])

Tenho certeza que isso pode ser reduzido muito mais. Adicionará a versão não destruída mais tarde.

Chris M
fonte
0

Javascript, 98 bytes

a=>{c="",l=0;for(w of a)while((i=w.indexOf(c))!=0||c!=w)alert(c=i!=0?c.substring(0,--l):c+w[l++])}

Resposta Java do Porto de Jakob

SuperStormer
fonte