Trouver tous les préfixes non ambigus d'un ensemble de chaînes

12

Pour ce défi, vous devez implémenter le Abbrevmodule Ruby dans le moins de code possible.

Défi

  • L'entrée sera tout ce que votre langue a comme un tableau (tableau, liste, séquence, etc.) de chaînes. Vous pouvez écrire une fonction ou accepter des mots séparés par des virgules sur STDIN.

  • Vous devez ensuite calculer l'ensemble de préfixes non ambigus pour ces chaînes. Cela signifie que vous devez renvoyer un hachage (ou une carte, un objet, etc.) d'abréviations à leurs chaînes d'origine.

    • Un "préfixe" est une sous-chaîne de la chaîne d'origine commençant au début de la chaîne. Par exemple, "pref" est un préfixe du mot "prefix".

    • Un préfixe non ambigu est celui qui ne peut signifier qu'un seul mot. Par exemple, si votre entrée est car,cat, ce can'est pas un préfixe sans ambiguïté, car cela pourrait signifier «voiture» ou «chat».

    • L'exception à cette règle est qu'un mot est toujours un préfixe de lui-même. Par exemple, si vous avez une entrée telle que car,carpet, car:cardoit être dans votre sortie.

  • Vous pouvez ensuite renvoyer le hachage / map / objet / etc. à partir de votre fonction (ou faites l'équivalent dans votre langue), ou imprimez-le par key:valuepaire sous STDOUT sous la forme de f:foo,fo:foo,.... (Les paires clé-valeur peuvent également être séparées par des espaces si cela raccourcit votre code.)

Cas de test

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

Règles

  • L'entrée ne contiendra pas d'éléments en double.

  • Votre sortie peut être dans n'importe quel ordre; vous n'avez pas à le trier.

  • Vous ne pouvez pas utiliser un Abbrevmodule / fonction / chose intégré comme Ruby.

  • Il s'agit de , donc le code le plus court en octets gagnera!

Poignée de porte
la source
Est-ce que stdout doit être exactement ce format? Ou puis-je faire key:value\nkey:value\nkey:value...?
métro monorail
4
Plutôt que de redéfinir l' abréviation du mot, vous pouvez simplement utiliser le préfixe avec sa signification standard. Et je pense que sans ambiguïté transmet la propriété souhaitée des touches plus efficacement que unique , pour laquelle ma première intuition était que vous ne vouliez qu'un seul préfixe par mot d'entrée.
Peter Taylor
@PeterTaylor Bonne idée; édité.
Poignée de porte
1
Peut-on imprimer plusieurs fois la même clé (avec la même valeur)?
xnor

Réponses:

1

APL (46)

(Oui, le jeu de caractères APL tient dans un octet, avec de la place à revendre.)

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

Il s'agit d'une fonction qui prend une liste de chaînes et renvoie une matrice 2 par N, où chaque ligne contient un préfixe non ambigu et le mot auquel elle appartient:

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

Explication:

  • ∆←⍵: stocke le bon argument dans .
  • {↑∘⍵¨⍳⍴⍵}¨∆: pour chaque élément de , obtenez les préfixes possibles de cet élément:
    • ⍳⍴⍵: obtenir une liste de 1la longueur de
    • ↑∘⍵¨: pour chacun de ces nombres, obtenez autant d'éléments .
  • ∪⊃,/: concaténer les listes ensemble et prendre les valeurs uniques.
  • {... : pour chacun des préfixes uniques:
    • ∆/⍨⊃¨⍵∘⍷¨∆: sélectionnez les mots qui commencent par ce préfixe
    • (⊂⍵),: place également le préfixe et concatène
    • ∆/⍨2=⍴∆←: ne renvoie la liste que s'il y a deux éléments (le préfixe et un mot correspondant)
  • : transformer la liste des tuples en matrice
marinus
la source
Le lien est rompu maintenant ...
user202729
3

Python 2,7 - 146 141 octets

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

Notez que l'indentation sur les lignes 4 et 5 n'est pas 4 espaces, c'est un effet secondaire de l'interpréteur de démarque de SE. C'est un caractère de tabulation littéral, donc un seul octet.

Ce n'est pas techniquement conforme, mais je vais le changer si Doorknob clarifie. Il utilise des sauts de ligne au lieu de virgules pour séparer la sortie. Par exemple:

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

Nouveau: j'ai pu me débarrasser de 5 caractères en affectant la chaîne que je vérifie à une variable e. Cela signifie que je n'ai qu'à taper eau lieu de w[:a]trois fois. Cela signifie également que je sauvegarde des personnages en faisant e=w[:a+1]et en changeant ...range(1,len(w)+1)en range(len(w)).


Explication:

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.
métro monorail
la source
Vous pouvez utiliser à la sum(b.startswith(e) for b in l)place delen(filter(lambda b:b.startswith(e),l))
Niklas B.
Vous pouvez également raccourcir b.startswith(e)en b.find(e)==0ou b[:a+1]==e, et vérifier <2le nombre au lieu de ==1.
xnor
e=""\n for a in w:\n\te+=afor a in range(len(w)):\n\te=w[:a+1]
Faites
J'ai créé ici une version non déprimée pour tous ceux qui en ont besoin gist.github.com/stuaxo/c371b2d410191a575b763b74719856c8
Stuart Axon
3

J - 47 car

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

J considère les chaînes comme de simples vecteurs de caractères, ce qui signifie que lorsqu'il essaie de faire une liste de chaînes, il finit par créer un tableau de caractères, de sorte que les extrémités sont remplies d'espaces. La solution de J à cela s'appelle la boîte , donc cette fonction prend comme argument une liste encadrée de chaînes, afin de conserver la longueur.

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

De plus, il manque un type de hachage à J, donc le plus proche de lui est un tableau d'éléments à deux colonnes, par exemple des chaînes encadrées. Si cela est inacceptable et que je dois utiliser par défaut le formulaire de valeur-clé, je peux reformater la sortie de ce formulaire en 67 caractères au total:

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

Explication par explosion:

(,.~~.@,[:(#~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

Exemples:

   (,.~~.@,[:(#~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,
algorithmshark
la source
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]

Version non golfée:

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

Exemple:

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

J'ai utilisé la initsfonction, qui trouve tous les préfixes d'une liste / chaîne. Est-ce que ça compte comme de la triche?

lortabac
la source
1
Vous pouvez remplacer concatMappar (=<<), qui se trouve dans le Prélude. Vous enregistre 10 caractères.
Rhymoid
@Rhymoid Merci. J'ai supprimé concatMapmais je ne peux pas enregistrer plus de 9 caractères.
lortabac
Oh attendez, vous avez raison; Haskell considère >>=\ comme un lexème unique. Désolé pour ça ...
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]

Nous parcourons les préfixes de chaque mot dans l'entrée, en imprimant la paire préfixe / mot correspondante si elle apparaît exactement une fois ou si elle correspond au mot entier. Nous profitons du comportement de court-circuit de or(et printétant une fonction) pour imprimer uniquement si l'une de ces conditions est remplie.

La whileboucle coupe à plusieurs reprises le dernier caractère pour créer des préfixes de plus en plus courts, se terminant lorsque la chaîne vide reste. C'est la seule fois où nous indexons ou découpons quelque chose.

Nous comptons les occurrences du préfixe edans l'entrée en recherchant les sous-chaînes Sdans la chaîne d' entrée séparée par des virgules d'origine ','+e. Nous ajoutons au préalable une virgule à la chaîne d'entrée. Cet ajout provoque un élément de chaîne vide supplémentaire lorsque nous split, mais cela n'a aucun effet car il n'a pas de sous-chaînes non vides.

Pour vérifier le cas où la sous e- chaîne est le mot entier w, nous les comparons en utilisant l'opérateur de comparaison de chaînes. Cela compare lexicographiquement, donc les préfixes plus courts sont plus petits. La double comparaison échoue si l'un e==wou l' autre S.count(c+e)<2.

Si l'impression des sorties dans le formulaire e,wétait autorisée, je sauverais un caractère en écrivant à la e+c+wplace.

Crédit undergroundmonorail de dont la réponse que je fondé ma structure de code globale.

xnor
la source
(e<w)*S.count(c+e)>1peut être joué e<w<w*S.count(c+e)pour enregistrer 2 caractères.
isaacg
@isaacg Merci! J'ai ajouté votre optimisation.
xnor
1

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

Non golfé:

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
la source
1

k4 (70)

pas particulièrement golfé; je suis sûr que ça pourrait être plus court

assez similaire au J impl. ci-dessus, je pense - recueille simplement tous les préfixes (appropriés), supprime à nouveau les mots des préfixes (pour gérer le cas "car"/ "carpet"), les regroupe en classes d'équivalence, sélectionne les classes avec un seul élément, les réduit des listes à chaînes et ajoute dans la carte des chaînes à eux-mêmes.

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

quelques cas de test

notez que dans k/ q, une chaîne est une liste de caractères, donc une chaîne ne contenant qu'un seul caractère doit être marquée comme telle en utilisant la ,fonction unaire ; & mmwrt une liste de chaînes ne contenant qu'une seule chaîne

ceux-ci utilisent qla showfonction, qui a un formatage intégré pour certaines structures de données, pour rendre les résultats plus lisibles:

  .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
la source
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)

Golf initial.

Contribution:

code,golf,going

Production:

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

Mat
la source
1

Perl, 93 77

Avec des nouvelles lignes et un retrait pour la lisibilité:

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

Un peu trop tard et trop long, mais je suis content qu'il soit finalement passé en dessous de 100. La fonction renvoie une liste qui peut être affectée à la variable de hachage:

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

et

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

En fait, la liste retournée n'est pas encore filtrée - la construction du hachage est terminée au moment de son affectation, c'est-à-dire la fonction extérieure. SI ce n'est pas propre / assez juste, ajoutez 3 pour compter et mettez le contenu de la fonction entre accolades, en ajoutant +- puis la fonction renvoie la référence de hachage «vraie».

user2846289
la source
1

Q: 44 octets

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

REMARQUES

  • Le langage Q a un noyau interne nommé en interne K4 (utilisé dans cette réponse et une autre réponse précédemment à cette question)

  • Pour tester le code, téléchargez l'interprète (kx.com, gratuit pour une utilisation non commerciale, prise en charge de Windows, Linux, Mac)

L'interprète admet deux syntaxes:

  • verbeux (noms plus lisibles, noms distincts pour les mœurs et les diades, plus de bibliothèques, ...). Charger le fichier source avec l'extension q ou un interpréteur interactif

  • compact (noyau interne fonctionnel, opérateurs à une lettre, même lettre pour les deux utilisations monad / diad, ...). Charger le fichier source avec l'extension k, ou un interpréteur interactif en mode k (écrire \ à l'invite). Le code doit être testé dans ce mode

Le code définit un lambda (fonction anonyme). Pour donner un nom à la fonction, nous avons besoin du nom du préfixe: (ex f: {..}), donc nécessite 46 octets

TESTER

(en supposant la fonction nommée: sinon remplacez f par le code)

f `code`golf`going

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

renvoie un dictionnaire (clés de syntaxe! valeurs). Les clés sont une liste de symboles (`symb`symb ..), et les valeurs une liste de liste de symboles. Si nous exécutons le sentente à l'interpréteur interactif, nous avons une présentation plus pratique (chaque clé et valeurs associées sur une ligne différente)

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

EXPLICATION

x est l'argument implicite du lambda

$x convertir la liste des symboles en liste de chaînes

(-1_)\ itère sur chaque élément de la liste des symboles

(se lit comme pour chaque chaîne calcule les préfixes (à l'itération de manger supprime le dernier caractère de la chaîne (-1_), jusqu'à la chaîne vide)

$ se transforme à nouveau en liste de symboles (liste de tous les préfixes)

p: et attribue à p

,/ tout raser (concatène et crée une structure à un niveau)

= classer -> pour chaque préfixe unique, associe les mots correspondants

#:' calcule la longueur (nombre de mots associés à chaque préfixe)

1= vrai si longueur = 1 (sans ambiguïté), faux sinon

& où -> index des vrais éléments

p in\: détermine pour tous les préfixes s'ils sont dans un préfixe non ambigu

(..)' applique (..) à chaque valeur à droite (préfixe non ambigu)

?0,&: -> distinct 0 concaténé où (faire face aux mots comme préfixe de lui-même)

p@ transformer des index en symboles

x!.. construire un dictionnaire avec x (mots) comme clés et .. comme valeurs

Lire comme:

  • Construisez et retournez un dictionnaire avec les mots comme clés et les valeurs.

  • ... valeurs d'index à des positions distinctes 0 (tous les mots) et où préfixe sans ambiguïté

  • ... sans ambiguïté calculé comme des préfixes qui n'apparaissent qu'à un seul mot (la liste de mots associée à chaque symbole a une longueur d'un)

  • ... listes résultant de la classification de tous les symboles uniques avec les mots correspondants

  • ... préfixes calculés en répétant drop dernier caractère de chaque mot

J. Sendra
la source
1

PHP 7.0, 67 octets (postdate le défi)

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

prend l'entrée des arguments de la ligne de commande; imprime une virgule de fin; courir avec -nr.

pour les PHP plus récents , ajoutez un octet: remplacez &apar ""<.

pour les anciens PHP, utilisez ces 70 octets:

PHP, 70 octets

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

Brachylog , 23 octets

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

Essayez-le en ligne!

Prend l'entrée sous forme de liste via la variable d'entrée et génère une liste de [key, value]paires via la variable de sortie. Toute chaîne d'entrée qui n'est pas le préfixe d'une autre chaîne d'entrée sera générée en tant que préfixe d'elle-même deux fois, bien que l'en-tête sur TIO le masque en utilisant pour obtenir la liste complète au lieu 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.
Chaîne indépendante
la source
Si les doublons dans la sortie ne sont pas tolérés, ajoutez trois octets pour envelopper le tout {}ᵘ, sauf s'il existe un moyen plus court d'exclure quelque chose sous forme de préfixe ou de générer chaque paire de sortie nécessaire sans la règle supplémentaire ∋gj.
Chaîne indépendante
1

APL (Dyalog Classic) , 38 octets

remercie Erik l'Outgolfer de me rappeler d'utiliser un codage de caractères à un octet

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

Essayez-le en ligne!

ngn
la source
1
Hum ... Je ne vois aucun des mauvais personnages que vous ne pouvez pas utiliser avec le SBCS d'Adám ici ...: P
Erik the Outgolfer
sans
m'en rendre
0

Python (127)

Je n'ai donc pas pu commenter @undergroundmonorail, mais je pensais qu'il serait préférable d'adopter une approche par dictionnaire? Je suis sûr qu'avec une certaine compréhension de la liste / du dictionnaire, cela pourrait aussi être considérablement réduit, mais je ne peux pas le faire fonctionner en sautant du 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

L'impression sortira le dictionnaire, non ordonné.

EDIT: Ahh j'ai raté la voiture: voiture / voiture: critères tapis. Peut-être un contrôle de longueur?

jaybee3
la source
Peut-être que je manque quelque chose, mais cela semble alternativement ajouter et supprimer l'entrée de préfixe à chaque fois qu'il est rencontré, donc un préfixe ambigu n'apparaîtrait-il pas s'il se produit en 3 mots?
xnor
0

Groovy - 212 caractères

Golfé:

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]})}

exemple de sortie:

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

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

Non golfé:

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
la source
0

Zsh , 95 octets

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

Essayez-le en ligne!

La seule façon de "renvoyer" un tableau associatif dans Bash / Zsh est de le déclarer sans le localmot - clé, puis d'y accéder dans la portée parent. Cela permettrait d'économiser un octet. Cependant, les E / S via des variables sont généralement mal vues, nous imprimons donc la définition du tableau à la place.

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
la source
0

Rubis , 84 octets

Je viens de remarquer qu'il existe déjà une solution Ruby existante, eh bien. Cela améliore fondamentalement l'ancienne solution en sélectionnant les préfixes de manière plus intelligente (éliminant la nécessité d'ajouter chaque mot en tant que "préfixe" à la fin) et en comptant les préfixes pour vérifier l'unicité avant de les ajouter au hachage, au lieu de remplacer la valeur par un mannequin s'il y a un doublon, puis effacer l'entrée.

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

Essayez-le en ligne!

Encre de valeur
la source