Retrocede y vuelve a escribir una lista de palabras

38

Aquí le mostramos cómo retroceder y volver a escribir de una cadena a otra:

  1. Comience desde la primera cadena.
  2. Elimine los caracteres al final hasta que el resultado sea un prefijo de la segunda cadena. (Esto puede tomar 0 pasos).
  3. Agregue caracteres al final hasta que el resultado sea igual a la segunda cadena. (Esto también puede tomar 0 pasos).

Por ejemplo, la ruta de fooabca se fooxyzve así:

fooabc
fooab
fooa
foo
foox
fooxy
fooxyz

Tarea

Dada una lista de palabras, escriba un programa que retroceda y vuelva a escribir su camino desde la cadena vacía, a todas las palabras de la lista en sucesión, de vuelta a la cadena vacía. Salida de todas las cadenas intermedias.

Por ejemplo, dada la lista de entrada ["abc", "abd", "aefg", "h"], la salida debería ser:

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

h

Reglas

Puede devolver o imprimir una lista de cadenas, o una sola cadena con algún delimitador de elección. Opcionalmente, puede incluir las cadenas vacías iniciales y finales. Se garantiza que la entrada contiene al menos una palabra, y cada palabra solo contiene letras minúsculas ASCII ( a- z). Editar: se garantiza que las cadenas consecutivas en la entrada no sean iguales entre sí.

Este es el ; el código más corto en bytes gana.

Una implementación de referencia en Python 3: ¡ Pruébelo en línea!

Lynn
fuente
44
@ rahnema1> escriba un programa que retroceda y vuelva a escribir desde la cadena vacía
Kritixi Lithos
3
¿Cómo sería la salida ["abc","abc"]?
Kritixi Lithos
1
@Emigna Oops, esto es exactamente eso, ¡pero en un bucle! Así que voy a seguir adelante y decir que esto es un duplicado de eso.
Lynn
44
@ Lynn No es exactamente lo mismo. Ese no incluye el reconocimiento de los prefijos comunes, siempre se reduce a un carácter.
Martin Ender
66
Caso de prueba:a,abc,abcde,abc,a,abc,abcde
Zgarb

Respuestas:

9

Perl, 43 bytes

42 bytes de código + -nbanderas.

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

Para ejecutarlo:

perl -nE 'chop$@,say$@while!s/^$@//;s/./say$@.=$&/ge' <<< "abc
abd
aefg
h"
Dada
fuente
esto imprime abc 3 veces
izabera
@izabera Hubo un espacio después de abchacer que se imprimiera 3 veces (pero en realidad, la primera y la tercera vez fue sin el espacio). Lo quité.
Dada
5

Java 8, 144 bytes

Este es similar a la implementación de referencia pero combina los dos whilebucles. Es una expresión lambda que acepta un 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++));}

Sin golf

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++));
}

Expresiones de gratitud

  • -38 bytes gracias a la sugerencia lambda de CAD97
Jakob
fuente
¿No es más barato usar en class Blugar de interface B? Puede ejecutar desde una clase de paquete privado. Además, considere usar un lambda como ya ha especificado Java8.
CAD97
@ CAD97 interface B{static void maines más corto que class B{public static void main.
Kevin Cruijssen
@ CAD97 No se me ocurrió una forma de incorporar las lambdas a esto, pero ayer me enteré de ellas. ¿Algunas ideas?
Jakob
1
Ah, estoy oxidado. Debería poder hacer a->{/*your code*/}, lo que asignará a una variable de tipo java.util.function.Consumer<String[]>. Sin embargo, no puedo probar en este momento.
CAD97
1
@JakobCornell Por defecto, PPCG permite el envío completo de programas o funciones. Para los idiomas con funciones anónimas (lambda), la función anónima por sí sola es una respuesta aceptable (por lo tanto, no tiene que incluir la variable para almacenarla). (Aunque en las presentaciones de Java es cortés proporcionar el tipo de lambda.)
CAD97
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
fuente
3

Retina , 39 bytes

El recuento de bytes asume la codificación ISO 8859-1.

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

Pruébalo en línea!

La entrada y la salida son listas separadas por salto de línea. La salida incluye la cadena vacía inicial y final.

Martin Ender
fuente
3

Jalea , 31 29 26 bytes

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

Pruébalo en línea!

Cómo 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
fuente
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
(""!).(++[""])

La última línea es una función anónima, que toma y devuelve una lista de cadenas. Pruébalo en línea!

Explicación

Mi solución es recursiva. Primero, ?es una función infija de ayuda: a?bda los primeros length acaracteres de b, o la totalidad de bif aes más larga. A continuación defino una función infija !. La idea es que a!x, donde ahay una cadena y xuna lista de cadenas, produce la ruta desde ala primera cadena hacia adentro xy vuelve a la cola de x. En la línea final defino una función anónima que agrega la cadena vacía, luego se aplica !a la cadena vacía y a la entrada.

Explicación 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
fuente
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

La entrada se da como ['abc', 'abcdef', 'abcfed'], o como [ "abc", "abcdef", "abcfed"].

Revisión 1: -11 bytes. El crédito va a @xnor por su publicación sobre los consejos de golf de Python, y a @Lynn por encontrar el consejo para mí y para mí por ser inteligente. Se hicieron dos cambios: en lugar de not s.startswith(i), usé s.find(i), y en lugar de i!=susar i>s.

Revisión 2: -4 bytes. El crédito me corresponde al darme cuenta de que cometí un error realmente tonto. En lugar de usar sangría de una sola pestaña y doble pestaña, usé sangría de un solo espacio y una sola pestaña.

Revisión 3: -6 bytes. El crédito va a @ mbomb007 por sugerir poner los ratos en una sola línea. También arreglé un error cambiando s.find(i)a i.find(s).

Revisión 4: -4 bytes. El crédito va a @xnor por darse cuenta de que no necesitaba almacenar la entrada en una variable.

Revisión 5: -1 byte. El crédito me corresponde por darme cuenta de que ['']es lo mismo que [s]cuando lo agrego a la entrada.

Hiperneutrino
fuente
Ponga whilecada una en una sola línea. Además, puede usar en <1lugar de not.
mbomb007
¡Buena respuesta! Hay un buen consejo de xnor sobre cómo evitarlostartswith .
Lynn
@ Lynn ¡Oh, gracias por el enlace! ¡Lo encontré realmente útil!
HyperNeutrino
@ mbomb007 Lo siento, no entiendo lo que quieres decir al poner el whiles en una sola línea. ¿Quieres decir como while s.find(i):s=s[:-1];print s? Además, gracias por la sugerencia sobre <1, pero he cambiado a algo aún más corto gracias a uno de los consejos de xnor en el hilo de consejos de Python.
HyperNeutrino
@AlexL. Sí, pon el tiempo así.
mbomb007
1

GNU M4, 228 o 232 bytes¹

(¹ dependiendo de si terminar el archivo con dnl\no no, todavía soy nuevo en golf y 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),$@)')

Además, se pueden guardar 3 bytes reemplazando el segundo argumento de substrfrom 0por la cadena vacía, pero eso generaría muchas advertencias en stderr.

Sin golf:

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)"
Novela de suspenso
fuente
1

PHP, 116 111 101 83 bytes

Nota: utiliza la codificación de Windows-1252.

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

Corre así:

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

Explicación

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.

Ajustes

  • Se guardaron 5 bytes al usar trim($c^$w,"\0")para verificar la coincidencia de subcadena en lugar de $c&&strpos($w,$c)!==0.
  • Se guardaron 2 bytes al usar ~ÿpara producir una cadena con un byte NUL en lugar de"\0"
  • Se guardaron 8 bytes utilizando el $c=$c.ÿ&$wsufijo $ccon el siguiente carácter de$w
  • Ahorró 18 bytes masivos al combinar la lógica de los 2 bucles internos en un solo bucle
  • Se corrigió un error con un caso de prueba de los comentarios, sin cambios en el recuento de bytes
aross
fuente
1

Lotes, 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

Calcular el prefijo común era engorroso.

Neil
fuente
0

PHP, 153 bytes

terriblemente largo :(

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
";}

Corre con php -nr '<ode>' <text1> <text2> ....

Titus
fuente
0

JavaScript (ES6), 135 bytes

Interesante desafío! Uso: g(["abc", "abd", "aefg", "h"]). Parece que no puedo guardar ningún byte escribiendo esto como una función, por lo que son dos. Nuevas líneas no incluidas en el recuento 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])

Estoy seguro de que esto se puede reducir mucho más. Agregará una versión no golfizada más tarde.

Chris M
fuente
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++])}

La respuesta Java del puerto de Jakob

SuperStormer
fuente