Substring sem repetição mais longo


33

Dada uma sequência como entrada, encontre a substring contígua mais longa que não possui nenhum caractere duas ou mais. Se houver várias dessas substrings, você também pode produzir. Você pode assumir que a entrada está no intervalo ASCII imprimível, se desejar.

Pontuação

As respostas serão classificadas primeiro pelo comprimento de sua própria substring não repetitiva mais longa e depois pelo comprimento total. Pontuações mais baixas serão melhores para ambos os critérios. Dependendo do idioma, isso provavelmente parecerá um desafio de com restrição de origem.

Trivialidade

Em alguns idiomas, atingir uma pontuação de 1, x (linguagem) ou 2, x (quebra-cabeças e outros tarpits de turing) é bastante fácil, no entanto, existem outros idiomas nos quais minimizar o substring não repetitivo mais longo é um desafio. Eu me diverti muito ao obter uma pontuação de 2 em Haskell, então eu encorajo você a procurar idiomas nos quais essa tarefa é divertida.

Casos de teste

"Good morning, Green orb!" -> "ing, Gre"
"fffffffffff" -> "f"
"oiiiiioiiii" -> "io", "oi"
"1234567890"  -> "1234567890"
"11122324455" -> "324"

Pontuação de envio

Você pode pontuar seus programas usando o seguinte snippet:


Caso de teste proposto: 11122324455Jonathan Allan percebeu que minha primeira revisão não a tratou corretamente.
Dennis

Caso de teste do @Dennis adicionado. Estou curioso para saber como isso aconteceu.
Assistente de trigo

2
Gerei todas as substrings (já classificadas por comprimento), depois desduplicei as substrings e mantive as que permaneceram. Infelizmente, isso altera a ordem; 11122ocorre depois 324, mas é deduplicado para 12.
Dennis

Gostaria de saber onde está a resposta em espaço em branco.
Magic Octopus Urn

Respostas:


13

C, pontuação 2,  747   720  662 bytes

L  [  1  <<  7  ]  ,  *  q  ,  *  r  ,  l  ,  d  ,  i  ,  c  ,  j  ,  s  ,  t  ,  k  =  1  <<  7  ;  h  (  )  {  q  =  s  +  i  +  j  ++  ;  *  q  %  k  &&  !  L  [  *  q  %  k  ]  ++  &&  h  (  ++  c  )  ;  }  g  (  )  {  q  =  s  +  i  ;  *  q  %  k  ?  z  (  k  )  ,  h  (  j  =  c  =  0  )  ,  c  >  d  &&  (  d  =  c  )  &&  (  l  =  i  )  ,  g  (  ++  i  )  :  0  ;  }  f  (  S  ,  T  )  {  s  =  S  ;  l  =  i  =  d  =  0  ;  g  (  t  =  T  )  ;  p  (  i  =  0  )  ;  }  p  (  )  {  q  =  s  +  l  +  i  ;  r  =  t  +  i  ;  i  ++  <  d  ?  p  (  *  r  =  *  q  )  :  (  *  r  =  0  )  ;  }  z  (  i  )  {  L  [  --  i  ]  =  0  ;  i  &&  z  (  i  )  ;  }

Funciona pelo menos no MinGW de 32 bits (com otimizações desativadas). Não usa uma única palavra-chave.

Aparentemente, também funciona no TIO com gcc e clang: experimente online! (Obrigado @Dennis!)

Ligue para:

int main()
{
    char str[1024];

    f("Good morning, Green orb!", str);
    puts(str);

    f("fffffffffff", str);
    puts(str);

    f("oiiiiioiiii", str);
    puts(str);

    f("1234567890", str);
    puts(str);

    f("L  [  1  <<  7  ]  ,  *  q  ,  *  r  ,  l  ,  d  ,  i  ,  c  ,  j  ,  s  ,  t  ,  k  =  1  <<  7  ;  h  (  )  {  q  =  s  +  i  +  j  ++  ;  *  q  %  k  &&  !  L  [  *  q  %  k  ]  ++  &&  h  (  ++  c  )  ;  }  g  (  )  {  q  =  s  +  i  ;  *  q  %  k  ?  z  (  k  )  ,  h  (  j  =  c  =  0  )  ,  c  >  d  &&  (  d  =  c  )  &&  (  l  =  i  )  ,  g  (  ++  i  )  :  0  ;  }  f  (  S  ,  T  )  {  s  =  S  ;  l  =  i  =  d  =  0  ;  g  (  t  =  T  )  ;  p  (  i  =  0  )  ;  }  p  (  )  {  q  =  s  +  l  +  i  ;  r  =  t  +  i  ;  i  ++  <  d  ?  p  (  *  r  =  *  q  )  :  (  *  r  =  0  )  ;  }  z  (  i  )  {  L  [  --  i  ]  =  0  ;  i  &&  z  (  i  )  ;  }");
    puts(str);
}

Saída:

O código com formatação um pouco mais legível:

L[1<<7],
*q, *r, l, d, i, c, j, s, t, k=1<<7;

h()
{
    q = s+i+j++;
    *q%k && !L[*q%k]++ && h(++c);
}

g()
{
    q = s+i;
    *q%k ? z(k), h(j=c=0), c>d && (d=c) && (l=i), g(++i) : 0;
}

f(S, T)
{
    s = S;
    l = i = d = 0;
    g(t=T);
    p(i=0);
}

p()
{
    q = s+l+i;
    r = t+i;
    i++<d ? p(*r=*q) : (*r=0);
}

z(i)
{
    L[--i] = 0;
    i && z(i);
}

E isso pode ser usado para gerar espaçamento adequado para obter a formatação com a pontuação 2: Experimente online!


C, pontuação 3, 309 bytes

i
,
j
,
l
,
c
,
d
;
f
(
\
c\
\
h\
\
a\
\
r
*
s
)
{
\
f\
\
o\
\
r
\
(
i
=
l
=
d
=
0
;
s
[
i
]
;
c
>
d
&&
(
d
=
c
)
&&
(
l
=
i
)
,
++
i
)
\
f\
\
o\
\
r
(
\
c\
\
h\
\
a\
\
r

L
[
\
1\
\
2\
\
8
\
]
=
{
j
=
c
=
0
}
;
s
[
i
+
j
]
&&
!
L
[
s
[
i
+
j
++
]
]
++
;
++
c
)
;
\
w\
\
r\
\
i\
\
t\
\
e
(
1
,
s
+
l
,
d
)
;
}

Experimente online!


10

Haskell , score 2, 492 ... 307 224 212 209 207 bytes

((yy:yyy))??ss|ss==yy  =  ""  |  yy==yy=yy:yyy??ss
ss??sss=ss
ss""=""

ss((ff:fff))  =  ff  :  ss  fff??ff
ff""=""

ff((xxx:xx))  =  ss((xxx:xx))##ff  xx
xx##xxx  |  ((((xx>>xx))<))  $  xxx>>xx=xxx|xx==xx=xx

Experimente online!

Jogou golfe literalmente centenas de bytes graças a WW e Ørjan Johansen !

Explicação

A função (??)pega um caractere ce uma string se retorna o prefixo mais longo sque não contém c. Sem jogar e não otimizado para pontuação:

c ?? (y:s)  
    | c==y = ""
    | True = y : c ?? s
c ?? s = s

A função ssusa (??)para encontrar o prefixo mais longo de caracteres exclusivos de uma determinada sequência:

ss (x:r) = x : (x ?? ss r)
ss "" = ""

(##)é uma função que pega duas strings e retorna a mais longa. A comparação de comprimento funciona repetindo a string xtantas vezes quanto xlong ( x>>y) e ylong ( y>>x) e verificando qual das strings resultantes é lexicograficamente maior.

x ## y
  | (x>>x) < (y>>x) = y
  | True = x

Finalmente, ffrecursa sobre a sequência de entrada, gera o prefixo mais longo com ss, determina recursivamente a substring não repetitiva mais longa da cauda da sequência e retorna o mais longo dos dois com (##):

ff "" = ""
ff (x:r) = ss(x:r) ## ff r

4
224 , principalmente fundindo a lista intermediária.
Ørjan Johansen

2
Combinei esta resposta com a que eu postei no chat anteriormente para obter 216 .
Assistente de Trigo

3
209 reordenando as coisas.
Ørjan Johansen

3
Com o anúncio de recompensas eu levei um outro olhar e percebeu o @truque realmente custa 2 bytes sobre apenas fazer ?dois caracteres: 207
Ørjan Johansen

5

Lua, pontuação 3, 274 bytes

g='g'..'s'..'u'..'b'  _G  [  'l'..'o'..'a'..'d'  ](  g[g  ](  "s  =...f  o  r d = # s - 1 , 0 , - 1 d  o f  or r = 1 , # s - d d  o t = s :s  ub  (r  ,r  +d  )i  f n  ot t:  fi  nd  '(  .)  .*  %1  't  he  n p  ri  nt  (t  )r  et  ur  n en  d e  n  d e  nd  ","  ",""))(...)

Nota: Lua 5.2 ou Lua 5.3 é necessária

Uso:

$ lua lnrs.lua "Good morning, Green orb!"
ing, Gre
$ lua lnrs.lua "fffffffffff"
f
$ lua lnrs.lua "oiiiiioiiii"
oi
$ lua lnrs.lua "1234567890"
1234567890
$ lua lnrs.lua "11122324455"
324

Ideia principal: intercalar tudo com espaços, inserir " "(dois espaços) para dividir identificadores longos

Código não destruído:

g = "gsub"
_G["load"](
   g[g](      -- g[g] == string.gsub - a function for substitution of substrings
      "The source of actual program, but two-space sequences were inserted in some places", 
      "  ",   -- we are replacing all two-space substrings
      ""      -- with an empty string
   )
)(...)

Programa atual (após remover todos os pares de espaços):

s = ...
for d = #s - 1, 0, -1 do
   for r = 1, #s - d do
      t = s:sub(r, r+d)
      if not t:find"(.).*%1" then
         print(t)
         return
      end
   end
end

BTW, o snippet JS para calcular a pontuação falha no meu código.


4

Retina 0.8.2 , 37 bytes, pontuação 9

.
$&$'¶
(.)(?<=\1.+).*

O#$^`
$.&
1G`

Experimente online! A tradução direta desta resposta na Retina 1 salva um byte usando em Nvez de O#. No entanto, se você jogar ingenuamente a resposta da Retina 1 até 28 bytes, sua pontuação na verdade aumenta para 10! Explicação:

.
$&$'¶

Gere todos os sufixos da entrada.

(.)(?<=\1.+).*

Para cada sufixo, use o prefixo até o primeiro caractere duplicado.

O#$^`
$.&

Ordene as seqüências restantes na ordem inversa do comprimento (ou seja, a mais longa primeiro).

1G`

Tome mais tempo.


4

Geléia , pontuação 2, 14 bytes

Ẇµµff  Q  €  Ṫ

Agradecemos a @ JonathanAllan pela pontuação -1, +7 bytes e por perceber um erro.

Experimente online!

Como funciona

Ẇµµff  Q  €  Ṫ  Main link. Argument: s (string)

Ẇ               Window; yield all substrings of s, sorted by length.
 µ              Begin a new chain. Argument: A (array of substrings)
  µ             Begin a new chain. Argument: A (array of substrings)
   f            Filter A by presence in itself. Does nothing.
       Q  €     Unique each; deduplicate all strings in A.
    f           Filter A by presence in the array of deduplicated substrings,
                keeping only substrings composed of unique characters.
             Ṫ  Tail; take the last (longest) kept substring.

4

Limpo , pontuação 7 5, 276 bytes

@[ss:s]=rr(pp[][ss:s])((@s))
@s=s
ee x[rr:xx]|e x rr=True=ee x xx
ee x xx=f
f=e'e'' '
e::!  Char  !  Char  ->Bool
e  _ _=  code  {

eqC
}
pp p[r:rr]|ee r p=p=pp(a r p)rr
pp a _=a
a  x[ll:l]=[ll:a x  l]
a l ll=[l]
l[]rr=e'l''l'
l ff[]=f

l[r:rr][ss:ll]=l rr ll
rr x y|l x y=y=x

Experimente online! Obrigado a @ Οurous por me mostrar que é possível chamar o código de máquina ABC diretamente de dentro do Clean. Isso permite livrar-se do gargalo anteriorimport que define a pontuação mínima em 7, mas precisa da palavra-chave codeque define a pontuação mínima em 5 para essa abordagem.

Uma versão não codificada e não otimizada para pontuação do código acima pode ser encontrada aqui: Experimente online!


Versão anterior com pontuação 7, 158 154 130 bytes

import  StdEnv  
@[xx:rr]=c(%[][xx:rr])(@rr)
@e=e
c s b|  length  s<  length  b=b=s
%s[xx:r]|  isMember xx s=s= %(s++[xx])r
%r _=r

Experimente online!

Com a importpontuação, o score não pode ficar abaixo de 7. Sem a importação, seria necessário implementar a igualdade em strings ou chars sem nenhuma função da biblioteca que provavelmente não seja possível, como pode ser visto na nova versão acima.


1
Você pode realmente implementar a igualdade usando o ABC embutido, o que deve reduzir a pontuação. Voltarei com uma modificação sugerida hoje mais tarde, se você estiver interessado.
Οurous 02/02

Por exemplo: igualdade de caracteres: tio.run/##S85JTcz7/…
Οurous

@Ourous A code block with raw ABC instructions, which can be used for primitive functions like integer addition, for linking with C, bypassing the type system... welcome down the rabbit hole! ( do cloogle ) certamente parece convidativo. Vou dar uma olhada amanhã, obrigado pela sugestão!
Laikoni

1
@ Οurous Obrigado novamente, com seu teste de igualdade de caracteres, a pontuação agora é 5.
Laikoni

Aliás, você não precisa -IL sinalizador, pois nada está sendo importado.
Οurous 07/02

3

Python 3 , pontuação 4, 155 bytes

exec(('l=la''mbd''a f'',e=en''ume''rat''e:m''ax''([f[ j  :k]  for  j,i in e ( f)f''or  k,i in e ( f )if  len  ( { *''f[j'':k]''})==k-''j],''key''=le''n)'))

Isso define uma função l.

Agradecemos a @xnor por apontar que cadeias de comprimento 3 não aumentam a pontuação, economizando 32 bytes.

Experimente online!


A cadeia pode estar em pedaços de 3, certo?
Xnor

@xnor Mudando o nome da função, de fato. Obrigado!
Dennis

3

Brachylog , pontuação 2, 19 bytes

s  ᶠ  l  ᵒ  ≠  ˢ  t

Experimente online!

Apenas uma velha e chata resposta "esvazie tudo". Pelo menos eu aprendi que os metapredicados podem ser afastados dos predicados e ainda funcionam (e os subscritos e parâmetros (paramétricos) não podem).

s ᶠ - encontre todas as substrings da string especificada

l ᵒ - ordená-los de acordo com seu comprimento (crescente por padrão)

≠ ˢ - selecione aqueles que possuem todos os elementos distintos

t - pegue a cauda (último elemento) disso - aquele com o maior comprimento


2

Pitão , 11 bytes, pontuação 4

-4 pontos graças a Dennis

e lD {I# .:

elD{I#.:Q      Full program, inputs "string" from stdin and outputs to stdout
e              The last element of the list generated by taking
      .:Q      All substrings of the input
     #         Filtered for
   {I          Being invariant over deduplicate i.e. being "non-repeating"
 lD            and sorted by length

Experimente online!


2

Casca , pontuação 2, 10 bytes

►IIËII≠IIQ

Experimente online!

Explicação

O programa é equivalente a isso:

►Ë≠Q  Implicit input.
   Q  List of substrings.
►     Find one that maximizes:
 Ë    all ordered pairs
  ≠   are inequal.

O interno Ëavalia todos os pares ordenados de seu argumento xe retorna length(x)+1se todos os resultados forem verdadeiros, caso contrário0 . Quando maximizamos isso, encontramos a cadeia mais longa que não possui caracteres repetidos.

Na submissão, apenas insiro a função de identidade Ientre cada função, duas vezes. Como é o mesmo que Ë, I≠é o mesmo e assim por diante, isso não altera a semântica. O único perigo é que uma função de ordem superior possa decidir usar um dos Is como argumento, mas felizmente isso leva a um erro de tipo em nosso programa, para que isso não aconteça.


2

Clojure, pontuação 4

#(  let  [N  (fn  [[_ & r]] r) R  (fn  R [f v c]  (if  c (R f (f v (  nth  c 0))  ( N  c)) v)) C  (fn  C  (  [i]  (C (  seq  i) 0)) ( [i  n]  (if i (C ( N  i )  (  inc n)) n)))  J  (fn  [c  i]  (assoc c (C  c) i)) I  (fn  F [f i n R]  (if ( =  (C  R) n) R (F f (f  i) n ( J  R (f  i)))))] ( apply  str  (R ( fn  [a  b] ( if  (< (C  a)  (C  b)) b a )) "" (  for  [k  (I N % (C  % ) [])]  (R  ( fn [ t  c ] ( if ( or ( = t (  str t) ) ((  set t)c))(apply  str t) ( J  t c)))[]k)))))

Oh cara, isso foi doloroso! Nimplementa next, Ré reduce, Cé count, Jé conj(funciona apenas para vetores) e Ié iterate. apply strexiste duas vezes porque, caso contrário, a entrada "aaaa" não retornaria uma string, mas um vetor [\a]. Felizmente eu consegui usar applye assoc, eu não sabia que você poderia associar um índice além do último elemento de um vetor:


Raspei um pouco de espaço: Experimente online!
Ørjan Johansen


1

Python 3, score 4, 317 bytes

exec(('%s'  *58  %(  's=','in','pu','t(',');','pr','in','t(','so','rt','ed','((s','[i',':j',']f','or',' j',' i','n ','ra','ng','e(','1,','le','n(','s)','+1',')f','or',' i',' i','n ','ra','ng','e(','j)','if',' l','en','(s','et','(s','[i',':j',']))','==l','en','(s','[i',':j',']))',',k','ey','=l','en',')[','-1','])')))

Try it online!

Unexeced code:

s=input();print(sorted((s[i:j]for j in range(1,len(s)+1)for i in range(j)if len(set(s[i:j]))==len(s[i:j])),key=len)[-1])

lambda a contains mbda which has score 5, and a function needs return which apparently can't be execed (so takes a score of at least 5 for eturn), so a full program was necessary. It's probably possible to golf down the unexeced code size quite a bit, but I can't see a quick clear improvement.


1

Alice, 40 bytes

/ii..nn$$@@BBww..DD~~FF..!!nn$$KK??oo@@

(Trailing newline)

Try it online!

The instruction pointer moves diagonally in ordinal mode, so only every other character is executed.

i.n$@Bw.D~F.!n$K?o@

i     take input
.n$@  terminate if empty
B     push all nonempty substrings, with the longest on the top of the stack
w     push return address (start main loop)
.     make copy of current substring
D     deduplicate characters
~     swap: this places the original above the deduplicated copy
F     Push the original string if it is a substring of the deduplicated copy
      (which can only happen if they're equal); otherwise push empty string
.!    place a copy on the tape
n$K   if the empty string was pushed, return to start of loop
o     output
@     terminate

1

Perl 6, score: 15 10 8, length: 46 55 62 bytes

{~m:ov/(.+)<!{$0.comb.repeated}>/.max(&chars)}

Test it

{~m:ov/(..*)<!{(($0)).comb.repeated}>{{}}/.max(&chars)}

Test it

{m:ov:i/(..*)<!{(($0)).comb.repeated}>{{}}/.max((&chars)).Str}

Test it

Expanded:

{    # bare block lambda with implicit parameter 「$_」

    m                          # match (implicitly against 「$_」)
    :overlap                   # in every single way possible
    :ignorecase                # add a 「:」 to break up substring
    /

      (..*)                    # match at least one character

      <!{
        (($0)).comb.repeated  # backtrack if there were repeats
      }>

      {{}}                    # anon hash in code block (no-op)
    /

    .max((&chars))            # get the longest

    .Str                      # coerce to a Str (from a Match object)
}

Score of 5 for 88 bytes. There might be a few places to golf bytes though
Jo King

1

Java 8, score 9 (384 B) 7 (401 B)

S -> { int s = 0 , e = 0 , l = 0 , x = 0 , y = 0 , b [ ] = new int [ 256 ] ; for ( ; x <S.  length  & y <S.  length  & l <S.  length  - x ; x ++ ) { b [S[x]] = 1 ; for ( y ++ ; y <S.  length  && b [S[y]] < 1 ; b [S[y ++]] = 1 ) ; if ( l < y - x ) { s = x ; e = y ; l = y - x ; } for ( ; y <S.  length  && x < y & S[x] != S[y  ];)b [S[x ++]] = 0 ; }  String g=""; for( ; s<e ; g+= S[s++]);  return  g;}
  • Initial version. Will go down from here. Score is 9 due to "ubstring ", so substring will be the first part to replace.
  • Score is now 7 due to " length", which I probably won't be able to reduce further.. I doubt it is possible to drop the four uses of length. If it is possible, " eturn" (6) might lower the score by 1 as final improvement, but I guess this is it (except maybe a small reduce in byte-count..)

Try it online.



0

Mathematica, score 11 9

Length@Last@Select[Subsequences[Characters@#],#==DeleteDuplicates  @#&]&

Shaving a couple of bytes off of the longest nonrepeating string by obscuring the function's name:

Length@Last@Select[Subsequences[Characters  @#],#==(  ToExpression@ 
StringJoin@@FromCharacterCode@{{68},{101},{108},{101},{116},{101},{68},{117},
{112},{108},{105},{99},{97},{116},{101},{115}}))@#&]&

0

Kotlin, score: 11 10 9 bytes, length: 227 246 245 bytes

indices
  .flatMap { p -> indices . map { p to p + it } }
  .  filter { (r,i) -> i < length  }
  .map { ( s , a )->substring  (  s,  a  ) }
  .  filter { it  .  groupBy  { it } .  none { ( k , v )->v . size>1 } }
  .maxBy { it.length }

The longest is ubstring, which is 9 chars

It is called like this:

val c = "Good morning, Green orb!"

fun String.c(): String? = indices
    .flatMap { p -> indices . map { p to p + it } }
    .  filter { (r,i) -> i < length  }
    .map { ( s , a )->substring  (  s,  a  ) }
    .  filter { it  .  groupBy  { it } .  none { ( k , v )->v . size>1 } }
    .maxBy { it.length }

fun main(args: Array<String>) {
    val text = """indices
    .flatMap { p -> indices . map { p to p + it } }
    .  filter { (r,i) -> i < length  }
    .map { ( s , a )->substring  (  s,  a  ) }
    .  filter { it  .  groupBy  { it } .  none { ( k , v )->v . size>1 } }
    .maxBy { it.length }"""
    val message = text.c()!!
    println(message)
    println(text.length)
    println(message.length)
    println(c.c())
}

Aren't you able to reduce it to 10 by adding an additional space between roupingBy and {?
Kevin Cruijssen

1
Nice find, I changed the other 11s and and got down to 10
jrtapsell

It is 10 chars, but the longest substring isn't roupingBy (which is 9 chars) but eachCount (with trailing space).
Erik the Outgolfer

roupingBy has a trailing space (visible in the markdown, but the renderer seems to strip it)
jrtapsell

Managed to reduce it to 9, fixing the trimming issue
jrtapsell


0

05AB1E, 22 bytes | Score: 2

Œ  ʒ  D  Ù  Q  }  é  ¤

-1 score + 7 bytes thanks to HeebyJeeby

Try it online!


05AB1E, 15 bytes | Score: 3

Œ ʒ D Ù Q } é ¤

Try it online!


05AB1E, 8 bytes | Score: 8

ŒʒDÙQ}é¤

Try it online!


05AB1E can actually do something rather cheap... adding whitespace into 05AB1E does nothing.

If there is a rule against this, I can also use ´ and like 7 other chars.


1
@HeebyJeebyMan because I'm a moron, got a problem with that?
Magic Octopus Urn

@HeebyJeebyMan kidding haha, thanks for the idea.
Magic Octopus Urn
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.