Encontre todos os prefixos inequívocos de um conjunto de strings

12

Para esse desafio, você deve implementar o Abbrevmódulo Ruby no menor código possível.

Desafio

  • A entrada será qualquer que seja o seu idioma como um array (array, lista, sequência, etc.) de strings. Você pode escrever uma função ou aceitar palavras separadas por vírgula no STDIN.

  • Você deve calcular o conjunto de prefixos inequívocos para essas seqüências. Isso significa que você deve retornar um hash (ou mapa, objeto etc.) de abreviações para suas strings originais.

    • Um "prefixo" é uma subcadeia de caracteres da string original, iniciando no início da string. Por exemplo, "pref" é um prefixo da palavra "prefix".

    • Um prefixo inequívoco é aquele que pode significar apenas uma palavra. Por exemplo, se sua entrada for car,cat, canão será um prefixo inequívoco, pois pode significar "carro" ou "gato".

    • A exceção a essa regra é que uma palavra é sempre um prefixo de si mesma. Por exemplo, se você tiver uma entrada como car,carpet, car:cardeve estar em sua saída.

  • Você pode então retornar o hash / mapa / objeto / etc. da sua função (ou faça o equivalente no seu idioma) ou imprima para STDOUT em key:valuepares na forma de f:foo,fo:foo,.... (Os pares de valores-chave também podem ser separados por espaços em branco se o código for mais curto.)

Casos de teste

Input  code,golf,going
Output c:code,co:code,cod:code,code:code,gol:golf,golf:golf,goi:going,goin:going,going:going

Input  pie
Output p:pie,pi:pie,pie:pie

Input  pie,pier,pierre
Output pie:pie,pier:pier,pierr:pierre,pierre:pierre

Input  a,dog
Output a:a,d:dog,do:dog,dog:dog

Regras

  • A entrada não conterá elementos duplicados.

  • Sua saída pode estar em qualquer ordem; você não precisa classificá-lo.

  • Você não pode usar um Abbrevmódulo / função / coisa embutida como o Ruby's.

  • Isso é , então o código mais curto em bytes vencerá!

Maçaneta da porta
fonte
O stdout precisa ser exatamente esse formato? Ou posso fazer key:value\nkey:value\nkey:value...?
Undergroundmonorail
4
Em vez de redefinir a abreviação da palavra, você pode apenas usar o prefixo com seu significado padrão. E acho que inequívoco transmite a propriedade desejada das chaves de maneira mais eficaz que a única , para a qual minha primeira intuição foi que você queria apenas um prefixo por palavra de entrada.
Peter Taylor
@PeterTaylor Good idea; editado.
Maçaneta
1
Pode-se imprimir a mesma chave várias vezes (com o mesmo valor)?
Xnor 21/05

Respostas:

1

APL (46)

(Sim, o conjunto de caracteres APL cabe em um byte, com espaço de sobra.)

{↑{∆/⍨2=⍴∆←(⊂⍵),∆/⍨⊃¨⍵∘⍷¨∆}¨∪⊃,/{↑∘⍵¨⍳⍴⍵}¨∆←⍵}

Essa é uma função que pega uma lista de cadeias e retorna uma matriz 2 por N, onde cada linha contém um prefixo inequívoco e a palavra à qual pertence:

{↑{∆/⍨2=⍴∆←(⊂⍵),∆/⍨⊃¨⍵∘⍷¨∆}¨∪⊃,/{↑∘⍵¨⍳⍴⍵}¨∆←⍵}'code' 'golf' 'going'
 c      code  
 co     code  
 cod    code  
 code   code   
 gol    golf  
 golf   golf  
 goi    going 
 goin   going 
 going  going 

Explicação:

  • ∆←⍵: armazena o argumento correto em .
  • {↑∘⍵¨⍳⍴⍵}¨∆: para cada elemento de , obtenha os possíveis prefixos desse elemento:
    • ⍳⍴⍵: obtenha uma lista 1com o comprimento de
    • ↑∘⍵¨: para cada um desses números, obtenha muitos elementos .
  • ∪⊃,/: concatene as listas e obtenha os valores exclusivos.
  • {... : para cada um dos prefixos exclusivos:
    • ∆/⍨⊃¨⍵∘⍷¨∆: selecione as palavras que começam com esse prefixo
    • (⊂⍵),: inclua também o prefixo e concatene
    • ∆/⍨2=⍴∆←: retorne a lista apenas se houver dois elementos (o prefixo e uma palavra correspondente)
  • : transformar a lista de tuplas em uma matriz
marinus
fonte
O link está quebrado agora ...
user202729
3

Python 2.7 - 146 141 bytes

l=raw_input().split(',')
for w in l:
 for a in range(len(w)):
    e=w[:a+1]
    if e==w or len(filter(lambda b:b.startswith(e),l))==1:print e+':'+w

Observe que o recuo nas linhas 4 e 5 não é de 4 espaços, isso é um efeito colateral do intérprete de redução de preço da SE. Esse é um caractere de tabulação literal, portanto, apenas um byte.

Tecnicamente, isso não está de acordo com as especificações, mas vou alterá-lo se a Maçaneta da porta esclarecer. Ele usa novas linhas em vez de vírgulas para separar a saída. Por exemplo:

$ python2 abbreviations.py <<< code,golf,golfing
c:code
co:code
cod:code
code:code
golf:golf
golfi:golfing
golfin:golfing
golfing:golfing

Novo: consegui me livrar de 5 caracteres atribuindo a string que estou verificando a uma variável e. Isso significa que eu só preciso digitar em evez de w[:a]três vezes. Isso também significa que eu salvo os personagens fazendo e=w[:a+1]e mudando ...range(1,len(w)+1)para range(len(w)).


Explicação:

l=raw_input().split(',') # Gets a line of input from stdin and splits it at every ',' to make a list
for w in l: # For each word in that list...

 for a in range(1,len(w)+1): # For each number a from 1 to the length of that word...

    if (w[:a]==w # w[:a] gets the string w up to the ath index. For example, 'aeiou'[:3] == 'aei'.
                 # We're testing every possible w[:a] to see if it's a unique abbreviation.
                 # However, a word is always its own abbreviation, so we hardcode that in by testing
                 # if w[:a] is the same as w.

or len(filter( # filter takes a function and an iterable as an argument, and returns a list of every
               # element of that iterable where that_function(that_element) returns a True-y value

lambda b:b.startswith(w[:a]),l) # We define an anonymous function that returns True for any string
                                # that begins with our current w[:a]. We filter for words that return
                                # True.

)==1): # If exactly one word returns True for this, it's a unique abbreviation!

     print w[:a]+':'+w # Print the abbreviation, a colon, and the full word.
undergroundmonorail
fonte
Você poderia usar sum(b.startswith(e) for b in l)em vez delen(filter(lambda b:b.startswith(e),l))
Niklas B.
Você também pode reduzir b.startswith(e)para b.find(e)==0ou b[:a+1]==ee verificar <2a contagem em vez de ==1.
Xnor 21/05
Também faça em e=""\n for a in w:\n\te+=avez de for a in range(len(w)):\n\te=w[:a+1]salvar 10 caracteres
WorldSEnder
Eu fiz uma versão ungolphed aqui para qualquer um que precisa dele gist.github.com/stuaxo/c371b2d410191a575b763b74719856c8
Stuart Axon
3

J - 47 char

(,.~~.@,~[:(#~1-1({.\e."_1]\.){."1)@;(<\,.<)&.>)

J vê as strings apenas como vetores de caracteres, o que significa que, quando tenta fazer uma lista de strings, acaba criando uma tabela de caracteres, para que as extremidades fiquem preenchidas com espaços. A solução de J para isso é chamada de caixa , de modo que esta função assume como argumento uma lista de seqüências de caracteres em caixa, para preservar o comprimento.

   'code';'golf';'going'
+----+----+-----+
|code|golf|going|
+----+----+-----+

Além disso, J não possui um tipo de hash, portanto, o mais próximo a ele é de uma tabela de itens de duas colunas, por exemplo, cadeias de caixa. Se isso for inaceitável e eu tiver que usar como padrão o formulário de valor-chave, posso reformatar a saída para este formulário em um total de 67 caracteres :

;@|.@,@((<&>',:'),."1,.~~.@,[:(#~1-1({.\e."_1]\.){:"1)@;(<,.<\)&.>)

Explicação por explosão:

(,.~~.@,[:(#~1-1({.\e."_1]\.){."1)@;(<\,.<)&.>) NB. unambiguous prefixes
                                    (     )&.>  NB. for each string:
                                     <\         NB.   take all prefixes
                                       ,.<      NB.   pair each with string
        [:                         ;            NB. gather up "partial" hashes
          (#~1-                  )@             NB. remove those rows where:
               1({.\        ){."1               NB.   each key
                    e."_1                       NB.   is an element of
               1(        ]\.){."1               NB.   the rest of the keys
 ,.~                                            NB. hash each word to itself
       ,                                        NB. add these rows to hash
    ~.@                                         NB. remove duplicate rows

Exemplos:

   (,.~~.@,[:(#~1-1({.\e."_1]\.){."1)@;(<\,.<)&.>) 'pie';'pier';'pierre'
+------+------+
|pie   |pie   |
+------+------+
|pier  |pier  |
+------+------+
|pierre|pierre|
+------+------+
|pierr |pierre|
+------+------+
   NB. 1-char words have to be made into lists with ,
   (,.~~.@,[:(#~1-1({.\e."_1]\.){."1)@;(<\,.<)&.>) (,'a');'dog'
+---+---+
|a  |a  |
+---+---+
|dog|dog|
+---+---+
|d  |dog|
+---+---+
|do |dog|
+---+---+
   NB. "key:value," format, reversed order to save chars
   ;@|.@,@((<&>',:'),."1,.~~.@,[:(#~1-1({.\e."_1]\.){:"1)@;(<,.<\)&.>) 'code';'golf';'going'
goin:going,goi:going,gol:golf,cod:code,co:code,c:code,going:going,golf:golf,code:code,
algoritmshark
fonte
2

Haskell 96 87

import Data.List
i=inits
f a=a>>= \x->[(y,x)|y<-i x,y/="",y`notElem`(a>>=i)\\i x||y==x]

Versão não destruída:

 import Data.List
 f a = concatMap (\x ->
     [(y, x) |
      y <- inits x,
      y /= "",
      y `notElem` concatMap inits a \\ inits x || y == x]
     ) a

Exemplo:

> f ["pi","pier","pierre"]
[("pi","pi"),("pier","pier"),("pierr","pierre"),("pierre","pierre")]

Eu usei a initsfunção, que encontra todos os prefixos de uma lista / string. Isso conta como trapaça?

Lortabac
fonte
1
Você pode substituir concatMappor (=<<), que está no Prelúdio. Economiza 10 caracteres.
Rhymoid
@Rhymoid Obrigado. Eu removi, concatMapmas não consigo salvar mais de 9 caracteres.
Lortabac #
Oh espere, você está certo; Haskell considera >>=\ como um único léxico. Desculpe por isso ...
Rhymoid
2

Python 3 (97)

c=','
S=c+input()
for w in S.split(c):
 e=w
 while e:e<w<w*S.count(c+e)or print(e+':'+w);e=e[:-1]

Nós iteramos sobre os prefixos de cada palavra na entrada, imprimindo o par correspondente de prefixo / palavra se ele aparecer exatamente uma vez ou for para a palavra inteira. Aproveitamos o comportamento de curto-circuito de or(e printsendo uma função) para imprimir apenas se uma dessas condições for atendida.

O whileloop corta repetidamente o último caractere para criar prefixos cada vez mais curtos, terminando quando a string vazia permanece. Essa é a única vez que indexamos ou dividimos em algo.

Contamos as ocorrências do prefixo ena entrada pesquisando na sequência de entrada original separada por vírgula Spor substrings ','+e. Anexamos uma vírgula à string de entrada beaforehand. Essa adição causa um elemento de seqüência de caracteres extra vazio quando nós split, mas isso não tem efeito porque não possui substrings não vazios.

Para verificar o caso em que a substring eé a palavra inteira w, comparamos usando o operador de comparação de cadeias. Isso se compara lexicograficamente, portanto, prefixos mais curtos são menores. A comparação dupla falha se e==wou S.count(c+e)<2.

Se a impressão de saídas no formulário e,wfosse permitida, eu salvaria um caractere escrevendo e+c+w.

Crédito para undergroundmonorail a partir de cuja resposta eu baseei minha estrutura geral de código.

xnor
fonte
(e<w)*S.count(c+e)>1pode ser jogado no golfe e<w<w*S.count(c+e)para salvar 2 caracteres.
Isaacg
@isaacg Thanks! Eu adicionei sua otimização.
xnor 21/05
1

Ruby, 114

def f(l);h={};l.each{|w|w.size.times{|i|k=w[0..i];h[k]=h[k]&&0||w}};h.delete_if{|k,v|v==0};l.each{|w|h[w]=w};h end

Ungolfed:

def f(list)
  hash = {}
  list.each do |word|
    word.size.times do |i|
      key = word[0..i]
      h[key] = (hash[key] && 0) || word
    end
  end
  hash.delete_if{|key, value| v==0}
  list.each{|word| hash[word] = word}
  hash 
end
dtldarek
fonte
1

k4 (70)

não particularmente jogado de golfe; tenho certeza que poderia ser mais curto

bem parecido com o J impl. acima, eu acho - basicamente apenas coleta todos os prefixos (apropriados), remove as palavras dos prefixos novamente (para manipular o "car"/ "carpet"case), agrupa-as em classes de equivalência, escolhe as classes com apenas um elemento, reduz-as das listas para strings e adiciona no mapa de strings para si mesmos.

f:{(x!x),*:'{(&1=#:'x)#x}{x@=y@:&~y in x}.,/'+{1_'(c#,x;(!c:#x)#\:x)}'x}

alguns casos de teste

observe que em k/ q, uma string é uma lista de caracteres; portanto, uma string contendo apenas um único caractere precisa ser marcada como tal usando a ,função unary ; & mmwrt uma lista de cadeias contendo apenas uma cadeia

qa showfunção use , que possui formatação interna para algumas estruturas de dados, para tornar os resultados mais legíveis:

  .q.show f("code";"golf";"going")
"code" | "code"
"golf" | "golf"
"going"| "going"
,"c"   | "code"
"co"   | "code"
"cod"  | "code"
"gol"  | "golf"
"goi"  | "going"
"goin" | "going"
  .q.show f@,"pie"
"pie"| "pie"
,"p" | "pie"
"pi" | "pie"
  .q.show f("pie";"pier";"pierre")
"pie"   | "pie"
"pier"  | "pier"
"pierre"| "pierre"
"pierr" | "pierre"
  .q.show f(,"a";"dog")
,"a" | ,"a"
"dog"| "dog"
,"d" | "dog"
"do" | "dog"
  .q.show f("car";"carpet")
"car"   | "car"
"carpet"| "carpet"
"carp"  | "carpet"
"carpe" | "carpet"
Aaron Davies
fonte
1

JavaScript - 212

w=prompt(o=[]).split(",");w.map(function(k,l){for(i=0;++i<k.length;){p=k.slice(0,i);if(w.filter(function(r,t){return t!=l}).every(function(r){return r.indexOf(p)}))o.push(p+":"+k)}o.push(k+":"+k)});console.log(o)

Golfe inicial.

Entrada:

code,golf,going

Resultado:

["c:code", "co:code", "cod:code", "code:code", "gol:golf", "golf:golf", "goi:going", "goin:going", "going:going"]

Matt
fonte
1

Perl, 93 77

Com novas linhas e recuo para facilitar a leitura:

sub f{
    (map{
        $h{$x}=[($x=$`.$&,$_)x!$h{$x}]while/./g;
        $_,$_
    }@_),map@$_,values%h
}

Um pouco tarde e muito tempo, mas estou feliz que finalmente tenha ficado abaixo de 100. A função retorna uma lista que pode ser atribuída à variável de hash:

%h = f(qw/code golf going pie pier pierre/);
print "$_ $h{$_}\n" for sort keys %h;

e

perl prefix.pl
c code
co code
cod code
code code
goi going
goin going
going going
gol golf
golf golf
pie pie
pier pier
pierr pierre
pierre pierre

Na verdade, a lista retornada ainda não foi filtrada - a construção de hash é concluída no momento de sua atribuição, ou seja, função externa. Se não estiver suficientemente limpo / limpo, adicione 3 para contar e coloque o conteúdo da função entre chaves, acrescentando +- então a função retorna a referência de hash 'true'.

user2846289
fonte
1

Q: 44 bytes

{x!p@'(?0,&:)'p in\:&1=#:'=,/p:`$(-1_)\'$x}

NOTAS

  • A linguagem Q possui um núcleo interno chamado internamente K4 (usado nesta resposta e outra resposta anterior a esta pergunta)

  • Para testar o código, faça o download do interpretador (kx.com, gratuito para uso não comercial, suporte para Windows, Linux, Mac)

O intérprete admite duas sintaxes:

  • verbose (nomes mais legíveis, nomes distintos para moands e diads, mais bibliotecas, ...). Carregar arquivo de origem com extensão q ou intérprete interativo

  • compacto (núcleo interno funcional, operadores de uma letra, mesma letra para ambos os usos monad / diad, ...). Carregue o arquivo de origem com extensão k ou intérprete interativo no modo k (write \ at prompt). O código deve ser testado neste modo

O código define um lambda (função anônima). Para dar um nome à função, precisamos do nome do prefixo: (ex f: {..}), portanto, requer 46 bytes

TESTE

(assumindo a função nomeada: caso contrário, substitua f pelo código)

f `code`golf`going

`code`golf`going!(`code`cod`co`c;`golf`gol;`going`goin`goi)

retorna um dicionário (chaves de sintaxe! valores). As teclas são uma lista de símbolos (`symb`symb ..) e valorizam uma lista de lista de símbolos. Se executarmos o sentente no intérprete interativo, teremos uma apresentação mais conveniente (cada chave e associar valores em uma linha diferente)

code | `code`cod`co`c
golf | `golf`gol
going| `going`goin`goi

EXPLICAÇÃO

x é o argumento implícito para o lambda

$x converter lista de símbolos em lista de cadeias

(-1_)\ itera sobre cada elem da lista de símbolos

(lê como para cada seqüência de caracteres calcula prefixos (na iteração final, cai o último caractere da seqüência de caracteres (-1_), até a sequência vazia))

$ transforma em uma lista de símbolos novamente (lista de todos os prefixos)

p: e atribui a p

,/ arrasar tudo (concatena e cria uma estrutura de um nível)

= classificar -> para cada prefixo exclusivo, associa as palavras correspondentes

#:' calcula o comprimento (número de palavras associadas a cada prefixo)

1= verdadeiro se comprimento = 1 (inequívoco), falso caso contrário

& onde -> índice de elementos verdadeiros

p in\: determina para todos os prefixos se eles estiverem no prefixo inequívoco

(..)' aplica (..) a cada valor à direita (prefixo inequívoco)

?0,&: -> 0 distinto concatenado onde (lidar com as palavras como prefixo de si mesmo)

p@ transformar índices em símbolos

x!.. construa um dicionário com x (palavras) como chaves e .. como valores

Leia como:

  • Construa e retorne um dicionário com as palavras como chaves e valores.

  • ... valores de índices em posições distintas 0 (todas as palavras) e em que prefixo inequívoco

  • ... inequívoco calculado como prefixos que aparecem apenas em uma palavra (a lista de palavras associada a cada símbolo tem o comprimento um)

  • ... lista resultante da classificação de todos os símbolos exclusivos com as palavras correspondentes

  • ... prefixos calculados repetindo o último caractere de gota de cada palavra

J. Sendra
fonte
1

PHP 7.0, 67 bytes (pós-desafio)

for(;a&$c=$s[++$k]??($s=$argv[++$i])[$k=+$t=!1];)echo$t.=$c,":$s,";

recebe entrada de argumentos de linha de comando; imprime uma vírgula à direita; corra com -nr.

para PHP mais recente , adicione um byte: Substitua &apor ""<.

para PHP antigo, use estes 70 bytes:

PHP, 70 bytes

for(;a&$s=$argv[++$i];)for($k=+$t="";a&$c=$s[$k++];)echo$t.=$c,":$s,";
Titus
fonte
1

Braquilog , 23 bytes

∋Xa₀Y;?↔⟨∋a₀⟩ᶜ1∧Y;X|∋gj

Experimente online!

Leva a entrada como uma lista através da variável de entrada e gera uma lista de [key, value]pares através da variável de saída. Qualquer string de entrada que não seja um prefixo de outra string de entrada será gerada como um prefixo de si mesma duas vezes, embora o cabeçalho no TIO oculte isso usando para obter a lista completa em vez de .

 X                         X
∋                          is an element of
                           the input variable
    Y                      and Y
  a₀                       is a prefix of
 X                         X.
             ᶜ             The number of ways in which
        ⟨∋  ⟩              an element can be selected from
     ;?↔⟨   ⟩              the input variable
    Y; ↔⟨ a₀⟩              such that it has Y as a prefix
              1            is equal to 1.
               ∧Y          Y is not necessarily 1,
                   |       and the output variable
                Y;X        is the list [Y, X].
                   |       If every choice from the first rule has been taken already,
                           the output variable is
                    ∋      an element of
                   |       the input variable
                     gj    paired with itself.
String não relacionada
fonte
Se duplicatas na saída não forem toleradas, adicione três bytes para agrupar tudo {}ᵘ, a menos que haja uma maneira mais curta de excluir algo de um prefixo ou gerar cada par de saída necessário sem a regra extra ∋gj.
String não relacionada
1

APL (Dyalog Classic) , 38 bytes

obrigado Erik, o Outgolfer, por me lembrar de usar uma codificação de caracteres de byte único

{⊃,/⍵{b,¨⍨(⊂¨⍵~⊃,/a~⊂⍵)∪b←⊂⊂⍺}¨a←,⍵}

Experimente online!

ngn
fonte
1
Hum ... eu não vejo nenhum dos personagens ruins que você não pode usar com o SBCS de Adám aqui ...: P
Erik, o Outgolfer
Sem perceber, eu escolhi a versão intérprete errado de novo ... obrigado por reduzir para metade a minha contagem de bytes :)
NGN
0

Python (127)

Então não pude comentar @undergroundmonorail, mas achei que seria melhor usar uma abordagem de dicionário? Tenho certeza de que, com alguma compreensão de lista / dicionário, ele também pode ser tremendamente reduzido, mas não é possível fazê-lo funcionar com o pop do dict.

i=raw_input().split(",")
d = {}
for x in i:
    for c in range(1,len(x)+1):
        if x[:c] in d:
            del d[x[:c]]
        else:
            d[x[:c]]=x
print d

A impressão exibirá o dicionário sem ordem.

EDIT: Ahh eu perdi o carro: carro / carro: critérios de carpete. Talvez uma verificação de comprimento?

jaybee3
fonte
Talvez esteja faltando alguma coisa, mas isso parece adicionar e excluir alternativamente a entrada do prefixo toda vez que for encontrada; portanto, um prefixo ambíguo não aparecerá se ocorrer em três palavras?
Xnor 21/05
0

Groovy - 212 caracteres

Golfe:

c="collectEntries";f="findAll";def g={def h=[:].withDefault{[]};it.each{def w->w.size().times{ h[w[0..it]] << w}};(h."$f"{k,v->v.size()==1}."$c"{k,v->[k,v[0]]}).plus(h."$f"{k,v->v.contains(k)}."$c"{k,v->[k,k]})}

saída de exemplo:

println g(["code","golf","going"])

[c:code, co:code, cod:code, code:code, gol:golf, golf:golf, goi:going, goin:going, going:going]

Ungolfed:

def g = { def list ->
    def hash = [:].withDefault{[]}
    list.each {
        def word -> word.size().times{ hash[word[0..it]] << word }
    }

    def map = hash.findAll{ k,v -> v.size() == 1 }.collectEntries{ k,v -> [k,v[0]] }
    map.plus(hash.findAll{ k,v -> v.contains(k) }.collectEntries{ k,v -> [k,k] }
    map
}
Michael Easter
fonte
0

Zsh , 95 bytes

local -A m
for w;{m[$w]=$w;x=
for c (${(s::)w})x+=$c&&[ ${(M)@:#$x*} = $w ]&&m[$x]=$w
}
local m

Experimente online!

A única maneira de "retornar" uma matriz associativa no Bash / Zsh é declarando-a sem a localpalavra - chave e acessando-a no escopo pai. Isso economizaria um byte. No entanto, a E / S por meio de variáveis ​​geralmente é desaprovada, portanto, imprimimos a definição da matriz.

local -A m                          # declare m as associative
                                    # "local" is shorter than "typeset"/"declare"
for w;{                             # for each word
    m[$w]=$w                        # the word is a prefix of itself
    x=                              # ensure x is empty
    for c (${(s::)w})               # for each character in the word
        x+=$c &&                    # append to x (building a prefix
          [ ${(M)@:#$x*} = $w ] &&  # if the only match is the word itself:
          m[$x]=$w                  # ... then x is a prefix of w
}
local m                             # print m
GammaFunction
fonte
0

Ruby , 84 bytes

Só notei que já existe uma solução Ruby existente, tudo bem. Isso basicamente melhora a solução antiga escolhendo prefixos de maneira mais inteligente (eliminando a necessidade de adicionar cada palavra como "prefixo" no final) e contando prefixos para verificar a exclusividade antes de adicioná-los ao hash, em vez de sobrescrever o valor com um manequim se houver uma duplicata e depois apagar a entrada.

->w{h={};w.map{|e|(1..e.size).map{|i|w.count{|d|d[0,i]==e[0,i]}<2?h[e[0,i]]=e:0}};h}

Experimente online!

Value Ink
fonte