Extraer una cadena de una cadena dada

17

Te dan una cadena y dos caracteres. Debe imprimir la cadena entre estos caracteres desde la cadena.

Entrada

La entrada primero contendrá una cadena (no vacía o null). En la siguiente línea, habrá dos caracteres separados por un espacio.

Desafío

Devuelve la cadena entre los dos caracteres.

Ejemplo

Hello! What's your name?
! ?

debería dar como resultado la salida:

" What's your name"

Reglas

  • La cadena no tendrá más de 100 caracteres y solo contendrá caracteres ASCII en el rango (espacio) a ~(tilde) (códigos de caracteres 0x20 a 0x7E, inclusive). Consulte la tabla ASCII para referencia.
  • Debe tomar la entrada de stdin (o la alternativa más cercana).
  • La salida debe estar entre comillas (" ).
  • Puede escribir un programa completo, o una función que toma entrada y da salida a la cadena final
  • Los dos caracteres solo contendrán caracteres ASCII en el rango (espacio) a ~(tilde) (códigos de caracteres 0x20 a 0x7E, inclusive). Ver tabla ASCII para referencia.
  • No hay garantía de que ambos caracteres estén en la cadena.
  • Si alguno de los caracteres no se encuentra en la cadena, imprima "null" .
  • Si alguno de los caracteres se encuentra más de una vez (a menos que ambos caracteres sean iguales) en una cadena, imprima "null".
  • Si ambos caracteres son el mismo carácter, imprima la cadena "null".

Casos de prueba

1)

<HTML>code</HTML>
> <                       --> "null"

2)

What's what?
' '                       --> "null"

3)

abcdefghijklmnopqrstuvwxyz
n k                       --> "lm"

4)

Testing...
e T                       --> ""

5)

Last test-case
  -                       --> "test"

Puntuación

Este es el código de golf, por lo que gana el envío más corto (en bytes).

Spikatrix
fuente
3
¿Pueden aparecer los caracteres en el orden opuesto en la cadena? Si es así, eso podría usar un caso de prueba.
Martin Ender
1
¿Qué pasa si la subcadena contiene un "? ¿Deberíamos rodearlo con otro par de citas y no preocuparnos por eso?
jimmy23013
@ MartinBüttner, sí. Vea el caso de prueba editado 3. Gracias por recordarme eso
Spikatrix
@ user23013, sí. Ejemplo de entrada: one"two-three \n" -salida: "two"( \nes una nueva línea)
Spikatrix
1
No soy fanático de los detalles complicados sobre los marcadores que no aparecen o aparecen varias veces. Creo que el problema sería más agradable de resolver con mayores garantías en las entradas.
xnor

Respuestas:

3

CJam, 34 33 32 bytes

'"l_l2%&2*2>NerN/0"null"t_,3=='"

Pruébelo en línea en el intérprete de CJam .

Idea

  1. Elimina el segundo personaje de la línea 2.

  2. Forme una cadena que consista en una sola copia de todos los caracteres que ambas líneas tienen en común.

  3. Repita la cadena resultante dos veces y descarte sus dos primeros caracteres.

    Esto da como resultado una cadena de dos caracteres (si los caracteres de la línea 2 son diferentes y ambos aparecen en la línea 1) o una cadena vacía.

  4. Reemplace los caracteres de la cadena resultante en la línea 1 por avances de línea.

  5. Dividir la línea 1 en saltos de línea.

    El segundo elemento de la matriz resultante será la cadena deseada si la matriz contiene exactamente tres fragmentos.

  6. Reemplace el primer elemento de la matriz con la cadena nula .

  7. Recupere el segundo elemento de la matriz si su longitud es 3 y el primero de lo contrario.

  8. Anteponer y agregar una comilla doble.

Código

'"       e# Push a double quote.
l_       e# Read one line from STDIN. Push a copy.
l2%      e# Read one line from STDIN. Only keep characters at odd indexes.
&        e# Intersect both strings.
2*2>     e# Repeat the intersection twice and discard the first two characters.
Ner      e# Replace the characters of the resulting string with linefeeds.
N/       e# Split the result at linefeeds.
0"null"t e# Replace the first element of the resulting array with "null".
_,3=     e# Push 1 if the length of the array is 3 and 0 otherwise.
=        e# Retrieve the corresponding element from the array.
'"       e# Push a double quote.
Dennis
fuente
2

CJam, 38 bytes

l:Tl2%f#_W-$2,=2,@f#$~T<>1>"null"?'"_o

Demasiado largo...

Explicación

l:T             e# Read a line and store in T.
l2%             e# Read the two characters into a list.
f#              e# Find each character in the list of two characters.
_W-             e# Copy and remove not found results.
$2,=            e# Sort and check if the result is exactly [0 1].
                e# If true:
2,@f#           e# Find 0 and 1 in the original results.
$               e# Sort.
~T<>            e# Get a slice of T between the two positions (left-closed).
1>              e# Remove the first character.
                e# If false:
"null"          e# The string "null".
?               e# End if.
'"_o            e# Append a quote and output another quote at the beginning.
jimmy23013
fuente
2

Pyth, 37 36 34 bytes

p?"null"njT9m/zd{J%2wt:z.uSmxzdJNN

Gracias a @isaacg por los dos bytes guardados.

Pruébelo en línea: Pyth Compiler / Executor

Explicación:

                                     implicit: z = first input line
                    w                second input line
                  %2                 only use every 2nd char
                 J                   and store in J
                {J                   set(J), gets rid of duplicates
            m/zd                     count the number of appearances of each char
        njT1                         != [1, 1] ([1,1] is 10 in base 9)
 ?      njT1m/zd{J%2w                ... if [1,1] != number of appearances else ...
  "null"                               string "null"
                           mxzdJ     find the index for each char
                          S          sort the indices
                      :z.u           take the substring of z using these indices
                     t               remove the first char

p                               NN  print '"' + ... + '"'
Jakube
fuente
*2]1es más corto [1 1)y - ... 1aún más corto.
isaacg
@isaacg -...1 no funciona, ya que también necesito verificar que haya exactamente dos números.
Jakube
2
Me acaba de ocurrir una manera de 3 caracteres para hacer [1 1): jT9.
isaacg
2

Python 3, 149 bytes

s,i=input(),input();a,b=s.find(i[0]),s.find(i[2]);print('"'+('null',[s[a+1:b],s[b+1:a]][b<a])[(s.count(i[0])==s.count(i[2])==1)*(a!=b)*(a*b>-1)]+'"')

Versión sin golf:

string, chars = input(), input()
a, b = string.find(chars[0]), string.find(chars[2])

    if string.count(chars[0]) == string.count(chars[2]) == 1 and a!=b and a*b>-1:
        if b<a:
            print('"' + string[b+1:a] + '"')
        else:
            print('"' + string[a+1:b] + '"')
else:
    print('"null"')

Esta es mi primera respuesta aquí, por lo que se agradecen los consejos y las críticas.

TheSidekick
fuente
2

Ruby, 108 95 94

->s,f,l{a,b=[f,l].map{|u|(f==l||s.count(u)>1)&&abort('"null"');s.index u}.minmax;p s[a+1...b]}

Y para la versión sin golf

def between(string, first, last)
    left, right = [first, last].map do |substring|
        abort('"null"') if first == last || string.count(substring) != 1
        string.index(substring)
    end.minmax
    p string[left + 1 ... right]
end
Dylan Frese
fuente
¿Por qué no puedo ver ningún resultado cuando ejecuto su código aquí ?
Spikatrix
@CoolGuy Es una función sin nombre, por lo que debe llamarla así. ->s,f,l{begin a,b=[f,l].map{|u|raise if f==l||s.count(u)>1;s.index u}.minmax;p s[a+1...b];rescue;p'null'end}["<html>test</html>",?>,?<]Al [...]final es lo que llama a la función.
blutorange
@blutorange, está bien. Eso funcionó, pero ¿cómo pruebo el último caso de prueba?
Spikatrix
@CoolGuy Use cadenas normalmente citadas:->s,f,l{begin a,b=[f,l].map{|u|raise if f==l||s.count(u)>1;s.index u}.minmax;p s[a+1...b];rescue;p'null'end}["Last test-case"," ","-"]
blutorange
En lugar de generar un error con raise, puede reemplazarlo raisecon una variable indefinida como _o y. Esto genera un NameError. Además, creo que podría guardar algunos bytes más sin un rescate explícito:->s,f,l{a,b=[f,l].map{|u|(f==l||s.count(u)!=1)&&p('null')&&exit;s.index u}.minmax;p s[a+1...b]}
blutorange
1

C, 192 bytes

f(){char b[101],c,d,*p,*t;scanf("%[^\n]%*c%c%*c%c",b,&c,&d);p=strchr(b,c);t=strchr(b,d);c==d||!p||!t||strchr(p+1,c)||strchr(t+1,d)?puts("\"null\""):printf("\"%s\"",p<t?(*t=0,p+1):(*p=0,t+1));}

Código sin golf:

f()
{
    char b[101],c,d,*p,*t; //Variables

    scanf("%[^\n]%*c%c%*c%c",b,&c,&d); //Scan input

    p=strchr(b,c);
    t=strchr(b,d); //Find occurrence of characters

    c==d         ||  //If both characters are the same
    !p           ||  //If no occurrence of first character found
    !t           ||  //If no occurrence of second character found
    strchr(p+1,c)||  //If two occurrence of first character found
    strchr(t+1,d) ?  //If two occurrence of second character found
    puts("\"null\"") //Print "null"
                  :  //else
    printf("\"%s\"",p<t?(*t=0,p+1):(*p=0,t+1)); //print the string
}

Pruébalo aquí

Spikatrix
fuente
1

Python 3, 172 bytes

x=input()
a=input()
a,b=a[0],a[2]
if(a!=b)&(x.count(b)==x.count(a)==1):
 if x.index(a)>x.index(b):q=a;a=b;b=q
 print('"'+x.split(a)[1].split(b)[0]+'"')
else:print('"null"')
Tim
fuente
1

Javascript ( ES6 ), 125 123 bytes

Idea robada en gran medida de la solución de @ edc65.

[a,,b]=(p=prompt)(s=p()),[,c,d,e,,f]=s.split(RegExp('(['+(a+b).replace(/\W/g,'\\$&')+'])'))
p('"'+(!e||f||c==e?null:d)+'"')

nderscore
fuente
Principalmente me gusta [a,,b]=, lo usaré la próxima vez. Como las expresiones regulares son una molestia, aquí hay una solución libre de [a,,b]=(P=prompt)(s=P()), P((s=s.split(a)).length==2& (s=[].concat(...s.map(s=>s.split(b)))).length==3 ?``"${s[1]}"``:null)
expresiones regulares
(la última cadena tiene plantillas, es difícil de poner en un comentario)
edc65
1

Python, 161 bytes

import re,sys
s,p=sys.stdin
m=re.match('[^%s]*([%s])([^%s]*)([%s])[^%s]*$'%((p[0]+p[2],)*5),s)
if m:g=m.group
print'"null"'if not m or g(1)==g(3)else'"'+g(2)+'"'

La solución usa principalmente una expresión regular para extraer la cadena. Para acomodar que las letras puedan coincidir en cualquier dirección, el inicio y el final de la parte coincidente permite cualquiera de las letras. Verificar que las letras que realmente coincidieron para ser diferentes excluyen que la misma letra coincida dos veces, así como que las dos letras en la entrada sean las mismas.

Este es mi primer intento de usar Python para obtener una respuesta aquí. Por lo tanto, los comentarios sobre posibles mejoras son bienvenidos. Particularmente tengo la sensación de que debe haber una forma de acortar la condición en la declaración impresa.

Reto Koradi
fuente
1

Python 3, 155 bytes

s,n,a,b=[input(),'null']+list(input())[::2];q,w=[s.find(a),s.find(b)];print('"'+{0>1:n,0<1:s[min(q,w)+1:max(q,w)],a==b:n}[s.count(a)==s.count(b)==1]+'"')

Pruébalo en línea

OrangeHat
fuente
1

golflua, 132 bytes

L=I.r()I,J=I.r():m("(.) (.)")i=L:f(I)j=L:f(J)K,c=L:g(I,'')_,b=K:g(J,'')?i>j i,j=j,i$w((i==j|c+b!=2)&'"null"'|'"'..L:s(i+1,j-1)..'"')

Respuesta bastante fea. El bit de entrada es un poco aproximado (y requiere dos líneas, primero con la cadena y segundo con los caracteres de corte). Encontrar la ubicación de las banderas es sencillo, pero demasiado largo para competir con otras respuestas. La salida es bastante fácil. Un programa Lua equivalente sería

Line1 = io.read()
Line2 = io.read()
I,J = Line2:match("(.) (.)")     -- boobs return the char flags
i = Line1:find(I)                -- find location of flags
j = Line1:find(J)
K,c = Line1:gsub(I,'')           -- replace flag w/ empty & store in K
_,b = K:gsub(J,'')               -- taking K ensures single flags fail
if i > j then i,j=j,i end        -- ensure we start low to high
if i==j or not (c+b == 2) then   -- if i & j are the same or not 2 counts, fail
   print('"null"')
else                             -- print the string otherwise
   print('"'..Line1:sub(i+1,j-1)..'"')
end
Kyle Kanos
fuente
¿Hay algún compilador en línea que pueda probar la versión de golf?
Spikatrix
No creo que haya una versión en línea, pero el código fuente está disponible . Es un mapeo 1: 1 de Lua (no una interpretación o traducción a Lua), por lo que el código Lua se puede probar en ideone .
Kyle Kanos
0

Perl, 65

#!perl -p0
$.*=s/\Q$1/
/g while s/ ?(.)\z//;/
(.*)
/;$_=$.-1?null:"\"$1\""

Esto requiere que no haya un carácter de nueva línea en la segunda línea de la entrada.

nutki
fuente
Buen trabajo. Sin embargo, parece que faltan las comillas dobles.
Dennis
@Dennis, arreglado. No entendí el ejemplo.
nutki
1
Todavía faltan las citas para el nullcaso.
Dennis