Extrair uma string de uma determinada string

17

Você recebe uma sequência e dois caracteres. Você precisa imprimir a sequência entre esses caracteres a partir da sequência.

Entrada

A entrada primeiro conterá uma sequência (não vazia ou null). Na próxima linha, haverá dois caracteres separados por um espaço.

Desafio

Retorna a string entre os dois caracteres

Exemplo

Hello! What's your name?
! ?

deve resultar na saída:

" What's your name"

Regras

  • A cadeia não terá mais de 100 caracteres e conterá apenas caracteres ASCII no intervalo (espaço) a ~(til) (códigos de caracteres 0x20 a 0x7E, inclusive). Consulte a tabela ASCII para referência.
  • Você deve receber informações da stdin(ou alternativa mais próxima).
  • A saída deve estar entre aspas ( ").
  • Você pode escrever um programa completo ou uma função que recebe entrada e gera a sequência final
  • Os dois caracteres conterão apenas caracteres ASCII no intervalo (espaço) a ~(til) (códigos de caracteres 0x20 a 0x7E, inclusive). Consulte a tabela ASCII para referência.
  • Não há garantia de que ambos os caracteres estejam na sequência.
  • Se algum dos caracteres não for encontrado na sequência, imprima "null".
  • Se algum dos caracteres for encontrado mais de uma vez (a menos que os dois sejam iguais) em uma sequência, imprima "null".
  • Se os dois caracteres forem o mesmo, imprima a sequência "null".

Casos de teste

1)

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

2)

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

3)

abcdefghijklmnopqrstuvwxyz
n k                       --> "lm"

4)

Testing...
e T                       --> ""

5)

Last test-case
  -                       --> "test"

Pontuação

Isso é código de golfe, então a submissão mais curta (em bytes) vence.

Spikatrix
fonte
3
Os caracteres podem ocorrer na ordem oposta na string? Nesse caso, isso poderia usar um caso de teste.
Martin Ender
11
E se a substring contiver um "? Devemos apenas cercá-lo com outro par de citações e não nos importar com isso?
jimmy23013
@ MartinBüttner, sim. Veja o caso de teste editado 3. Obrigado por me lembrar sobre isso
Spikatrix 18/15
@ user23013, Sim. Exemplo input: one"two-three \n" -output: "two"( \nis newline)
Spikatrix
11
Não sou fã dos detalhes minuciosos sobre os marcadores não aparecerem ou aparecerem várias vezes. Eu acho que o problema seria mais agradável de resolver com garantias mais fortes sobre os insumos.
Xnor

Respostas:

3

CJam, 34 33 32 bytes

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

Experimente online no intérprete CJam .

Idéia

  1. Remova o segundo caractere da linha 2.

  2. Forme uma sequência que consiste em uma única cópia de todos os caracteres que ambas as linhas têm em comum.

  3. Repita a sequência resultante duas vezes e descarte seus dois primeiros caracteres.

    Isso resulta em uma cadeia de dois caracteres (se os caracteres da linha 2 forem diferentes e ocorrerem na linha 1) ou em uma cadeia vazia.

  4. Substitua os caracteres da sequência resultante na linha 1 pelos feeds de linha.

  5. Divida a linha 1 nos feeds de linha.

    O segundo elemento da matriz resultante será a sequência desejada se a matriz contiver exatamente três pedaços.

  6. Substitua o primeiro elemento da matriz pela sequência nula .

  7. Recupere o segundo elemento da matriz se seu comprimento for 3 e o primeiro caso contrário.

  8. Anexe e adicione uma aspas duplas.

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
fonte
2

CJam, 38 bytes

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

Demasiado longo...

Explicação

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
fonte
2

Pitão, 37 36 34 bytes

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

Obrigado a @isaacg pelos dois bytes salvos.

Experimente online: Pyth Compiler / Executor

Explicação:

                                     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
fonte
*2]1é mais curto que [1 1)e - ... 1ainda é mais curto.
Isaacg
@isaacg -...1não funciona, pois também preciso verificar se existem exatamente dois números.
Jakube
2
Eu apenas pensei em uma maneira de 3 caracteres para fazer [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)]+'"')

Versão Ungolfed:

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 é a minha primeira resposta aqui, por isso dicas e críticas são muito apreciadas.

TheSidekick
fonte
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]}

E para a versão ungolfed

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
fonte
Por que não consigo ver nenhuma saída quando executo seu código aqui ?
Spikatrix
@CoolGuy É uma função sem nome, então você precisa chamá-la assim ->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>",?>,?<]O [...]final é o que chama a função.
Blotange
@blutorange, Ok. Isso meio que funcionou, mas como testo o último caso de teste?
Spikatrix
@CoolGuy usar strings normalmente citados:->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
Em vez de gerar um erro com raise, você pode substituir raisepor uma variável indefinida como _ou y. Isso gera um NameError. Além disso, eu acho que você poderia salvar um pouco mais bytes sem um resgate explícita:->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 não destruído:

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
}

Teste aqui

Spikatrix
fonte
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
fonte
1

Javascript ( ES6 ), 125 123 bytes

Idéia roubada pesadamente da solução da @ 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
fonte
Eu gosto principalmente [a,,b]=, vou usá-lo na próxima vez. Como regexs são um aborrecimento, aqui é uma solução gratuita regex:[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)
edc65
(a última seqüência é templated, difícil de colocar em um comentário)
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)+'"'

A solução geralmente usa apenas uma expressão regular para extrair a string. Para acomodar que as letras possam corresponder em qualquer direção, o início e o final da parte correspondente permitem uma das letras. A verificação de que as letras que realmente corresponderam a diferentes exclui que a mesma letra seja correspondida duas vezes, e as duas letras na entrada sejam iguais.

Esta é minha primeira tentativa de usar o Python para obter uma resposta aqui. Portanto, o feedback sobre possíveis melhorias é muito bem-vindo. Sinto particularmente que deve haver uma maneira de reduzir a condição na declaração impressa.

Reto Koradi
fonte
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]+'"')

Experimente online

OrangeHat
fonte
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)..'"')

Resposta muito feia. O bit de entrada é um pouco áspero (e requer duas linhas, primeiro com a string e segundo com os caracteres de fatia). Encontrar os locais das bandeiras é simples, mas é muito longo para competir com outras respostas. A saída é bem fácil. Um programa Lua equivalente seria

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
fonte
Existe algum compilador online que eu possa testar a versão golfed?
Spikatrix # 21/15
Não acredito que exista uma versão online, mas o código fonte está disponível . É um mapeamento 1: 1 de Lua (não uma interpretação ou tradução para Lua), para que o código Lua possa ser testado em ideone .
Kyle Kanos #
0

Perl, 65

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

Isso requer que não haja caracteres de nova linha na segunda linha da entrada.

nutki
fonte
Bom trabalho. Parece que faltam aspas duplas.
Dennis
@Dennis, fixo. Eu não entendi o exemplo.
nutki
11
Ainda faltam as aspas para o nullcaso.
Dennis