Bir dizi dizenin açık öneklerini bulma


12

Bu meydan okuma için Ruby Abbrevmodülünü olabildiğince az kodda uygulamalısınız .

Meydan okuma

  • Giriş, dilinizin dizeler dizisi (dizi, liste, dizi vb.) Olarak sahip olduğu her şey olacaktır. Bir işlev yazabilir veya STDIN üzerinde virgülle ayrılmış sözcükleri kabul edebilirsiniz.

  • Daha sonra bu dizeler için açık önek kümesini hesaplamanız gerekir. Bu, kısaltmaların karma değerini (veya eşlemini, nesnesini, vb.) Orijinal dizelerine döndürmeniz gerektiği anlamına gelir.

    • Bir "önek", dizenin başında başlayan orijinal dizenin bir alt dizesidir. Örneğin, "pref", "prefix" kelimesinin bir önekidir.

    • Bir açık öneki sadece tek kelime anlamına gelebilir biridir. Girişinizi ise Örneğin, car,catdaha sonra cao da "araba" veya anlamına gelebilir çünkü kesin bir önek değil "kedi."

    • Bu kuralın istisnası, bir kelimenin her zaman kendi önekidir. Eğer olarak girdi böyle varsa Örneğin, car,carpet, car:carçıktınıza olmalıdır.

  • Daha sonra hash / map / object / etc öğesini döndürebilirsiniz. işlevinden (veya kendi dilinizde eşdeğerini yapın) veya STDOUT'a key:valueçiftler halinde yazdırın f:foo,fo:foo,.... (Anahtar / değer çiftleri, kodunuzu kısaltırsa boşlukla da ayrılabilir.)

Test senaryoları

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

kurallar

  • Giriş, yinelenen öğeler içermeyecektir.

  • Çıktınız herhangi bir sırada olabilir; sıralamak zorunda değilsiniz.

  • AbbrevRuby gibi yerleşik bir modül / işlev / şey kullanamazsınız .

  • Bu , bu yüzden bayt içindeki en kısa kod kazanacak!


Stdout tam olarak bu formatta olmalı mı? Yoksa yapabilir miyim key:value\nkey:value\nkey:value...?
yeraltı

4
Aksine kelime yeniden tanımlanması daha kısaltmasını sadece kullanabilirsiniz öneki standart anlamı ile. Ve bence açık bir şekilde , tuşların istenen özelliğini benzersizden daha etkili bir şekilde iletiyor, bunun için ilk sezgim, giriş kelimesi başına sadece bir önek istemenizdi.
Peter Taylor

@PeterTaylor İyi fikir; düzenlendi.
Kapı tokmağı

1
Aynı tuş birden çok kez basılabilir (aynı değerde)?
xnor

Yanıtlar:


1

APL (46)

(Evet, APL karakter seti boş bir alana sahip bir bayta sığar.)

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

Bu, bir dize listesi alan ve her satırın belirsiz bir önek içerdiği ve ait olduğu kelimeyi içeren 2'ye 2 matrisi döndüren bir işlevdir:

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

Açıklama:

  • ∆←⍵: doğru argümanı saklayın .
  • {↑∘⍵¨⍳⍴⍵}¨∆: öğesinin her bir öğesi için , o öğenin olası öneklerini alın:
    • ⍳⍴⍵: listesinden 1uzunluğa kadar bir liste alın
    • ↑∘⍵¨: bu sayıların her biri için, o kadar çok eleman alın .
  • ∪⊃,/: listeleri bir araya getirin ve benzersiz değerleri alın.
  • {... : benzersiz öneklerin her biri için:
    • ∆/⍨⊃¨⍵∘⍷¨∆: bu önekle başlayan kelimeleri seç
    • (⊂⍵),: ayrıca öneki de dahil eder ve birleştirir
    • ∆/⍨2=⍴∆←: listeyi yalnızca iki öğe (önek ve eşleşen bir sözcük) varsa döndür
  • : tuples listesini bir matrise dönüştürün

Bağlantı şimdi kesildi ...
user202729

3

Python 2.7 - 146 141 bayt

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

4. ve 5. satırlardaki girintinin 4 boşluk olmadığını, SE'nin işaretleme yorumlayıcısının bir yan etkisi olduğunu unutmayın. Bu gerçek bir sekme karakteri, bu yüzden sadece bir bayt.

Bu teknik olarak teknik özelliklere bağlı değildir, ancak Doorknob açıklığa kavuşursa değiştireceğim. Çıktıyı ayırmak için virgül yerine satırsonu kullanır. Örneğin:

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

Yeni: Bir değişkene kontrol ettiğim dizeyi atayarak 5 karakterden kurtulabildim e. Sadece yazmak zorunda Bu araçlar eyerine w[:a]üç kez. Ayrıca ben yaparak karakterleri kaydetmek demektir e=w[:a+1]ve değişen ...range(1,len(w)+1)için range(len(w)).


Açıklama:

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.

Bunun sum(b.startswith(e) for b in l)yerine kullanabilirsinizlen(filter(lambda b:b.startswith(e),l))
Niklas B.

Ayrıca kısaltabilir b.startswith(e)için b.find(e)==0ya b[:a+1]==eve çek <2yerine deyince ==1.
xnor

Ayrıca 10 karakter kaydederken e=""\n for a in w:\n\te+=abunun yerine yapınfor a in range(len(w)):\n\te=w[:a+1]
WorldSEnder

Burada ihtiyacı olan herkes için ungolphed versiyonu yaptım gist.github.com/stuaxo/c371b2d410191a575b763b74719856c8
Stuart Axon

3

J - 47 karakter

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

J, dizeleri sadece karakter vektörleri olarak görür, yani dizelerin bir listesini yapmaya çalıştığında aslında bir karakter tablosu oluşturmaya başlar, böylece uçlar boşluklarla doldurulur. J'nin buna çözümü kutu olarak adlandırılır , bu nedenle bu işlev argüman olarak uzunluğu korumak için kutulu bir dize listesi alır.

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

Ayrıca, J bir karma türünden yoksundur, bu yüzden buna en yakın olanı, örneğin kutulu dizeler gibi iki sütunlu bir tablodur. Bu kabul edilemez ve anahtar-değer formunu varsayılan olarak ayarlamam gerekiyorsa, bu forma çıktıyı toplam 67 karakterle yeniden biçimlendirebilirim :

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

Patlama ile açıklama:

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

Örnekler:

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

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]

Ungolfed sürümü:

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

Misal:

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

initsBir liste / dizenin tüm öneklerini bulan fonksiyonu kullandım . Hile olarak sayılır mı?


1
Sen yerini alabilir concatMaptarafından (=<<)Prelude olan. Size 10 karakter kazandırır.
Rhymoid

@Rhymoid Teşekkür ederim. Kaldırdım concatMapancak 9'dan fazla karakter kaydedemiyorum.
lortabac

Oh bekle, haklısın; Haskell >>=\ tek bir sözlük olarak kabul eder. Üzgünüm ...
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]

Girişteki her kelimenin önekleri üzerinde yinelenir, tam olarak bir kez görünüyorsa veya tam kelimeye aitse ilgili önek / kelime çiftini yazdırırız. Yalnızca bu koşullardan biri karşılandığında yazdırmak için kısa devre davranışından or(ve printişlev olarak) yararlanıyoruz.

whileDöngü sürekli alırken boş dize kalıntıları sonlandırma, daha kısa ve daha kısa önekleri oluşturmak için son karakteri keser. Endekslediğimiz veya herhangi bir şeye böldüğümüz tek zamandır.

eVirgülle ayrılmış orijinal girdi dizesini Salt dizeler için arayarak girdideki önek oluşumlarını sayarız ','+e. Bu nedenle giriş dizesine virgül koyuyoruz. Bu ekleme, biz boş bir dize öğesine neden olur split, ancak bunun bir etkisi yoktur, çünkü boş olmayan alt dizeleri yoktur.

Alt dizenin etüm kelime olduğu durumu kontrol etmek için wdize karşılaştırma operatörünü kullanarak bunları karşılaştırırız. Bu sözlükbilimsel olarak karşılaştırılır, bu nedenle daha kısa önekler daha küçüktür. İkisi karşılaştırma ya e==wda olursa başarısız olur S.count(c+e)<2.

Formdaki çıktıların yazdırılmasına e,wizin verilmişse, e+c+wbunun yerine yazarak bir karakteri kaydederdim.

Kredi undergroundmonorail gelen kimin cevap benim genel kod yapısını esaslı.


(e<w)*S.count(c+e)>1e<w<w*S.count(c+e)2 karakter kaydetmek için golf olabilir .
isaacg

@isaacg Teşekkürler! Optimizasyonunuzu ekledim.
xnor

1

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

1

k4 (70)

özellikle golf değil; eminim daha kısa olabilir

J impl ile oldukça benzer. Yukarıda, bence - temelde tüm (uygun) önekleri toplar, öneklerden kelimeleri tekrar kaldırır ( "car"/ case'i işlemek için "carpet"), bunları denklik sınıflarına gruplar, sadece bir öğeyle sınıfları alır, dize ve haritadan dize ekler.

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

bazı test senaryoları

k/ qiçinde bir dizenin karakter listesi olduğunu unutmayın , bu nedenle yalnızca tek bir karakter içeren bir dizenin tekli ,işlev kullanılarak bu şekilde işaretlenmesi gerekir ; & mmwrt yalnızca tek bir dize içeren bir dize listesi

Bunları kullanmak q'ın showyerleşik bazı veri yapıları için biçimlendirme fonksiyonu, sonuç daha okunabilir hale getirmek için:

  .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"

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)

İlk golf.

Giriş:

code,golf,going

Çıktı:

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


1

Perl, 93 77

Okunabilirlik için yeni satırlar ve girinti ile:

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

Biraz çok geç ve çok uzun, ama sonunda 100'ün altına düştüğüne sevindim. İşlev, karma değişkenine atanabilen bir liste döndürür:

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

ve

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

Aslında, iade edilen liste henüz filtrelenmemiştir - sağlama işlemi, görevlendirme sırasında tamamlanır, yani dış işlev. EĞER temiz / adil yeterli değil, prepending, saymak ve küme parantezleri içine koymak fonksiyon içerikleri 3 ekle +- daha sonra işlevi true 'karma referansı.


1

Q: 44 Bayt

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

NOTLAR

  • Q dili, dahili olarak K4 adında bir iç çekirdeğe sahiptir (bu cevapta ve daha önce bu soruya daha önce verilen bir cevapta kullanılır)

  • Kodu test etmek için yorumlayıcı indirin (kx.com, ticari olmayan kullanım için ücretsiz, Windows, Linux, Mac desteği)

Tercüman iki sözdizimini kabul eder:

  • ayrıntılı (daha okunabilir adlar, moand ve diadler için farklı adlar, daha fazla kütüphane, ...). Kaynak dosyasını q uzantılı veya etkileşimli yorumlayıcı ile yükleme

  • kompakt (fonksiyonel iç çekirdek, bir harf operatörleri, her iki kullanım için aynı harf monad / diad, ...). Kaynak dosyasını k uzantılı veya etkileşimli yorumlayıcıyı k modunda yükleyin (komut isteminde write \). Kod bu modda test edilmelidir

Kod bir lambda (anonim işlev) tanımlar. İşleve ad vermek için önek adına ihtiyacımız var: (ex f: {..}), bu yüzden 46 Bayt gerektirir

ÖLÇEK

(adlandırılmış işlev varsayılırsa: aksi takdirde kod yerine f kullanılır)

f `code`golf`going

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

bir sözlük döndürür (sözdizimi tuşları! değerler). Tuşlar, sembollerin bir listesidir ("symb`symb ..") ve sembollerin listesini listeler. Cümleyi etkileşimli yorumlayıcıda yürütürsek, daha uygun bir sunumumuz olur (her bir anahtar ve ilişkilendirilen değerler farklı bir satırda)

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

AÇIKLAMA

x lambda için örtük argüman

$x sembol listesini dize listesine dönüştür

(-1_)\ sembol listesinin her bir elemini tekrarlar

(her dize için önekleri hesaplar gibi okunur (yemek yinelemesinde boş dizeye kadar dizenin son karakterini (-1_) düşer)

$ tekrar sembol listesine dönüşür (tüm öneklerin listesi)

p: ve p'ye atar

,/ hepsini övün (tek seviyeli bir yapıyı birleştirir ve oluşturur)

= sınıflandırmak -> her benzersiz önek için, ilgili kelimeleri ilişkilendirir

#:' uzunluğu hesaplar (her önekle ilişkilendirilmiş kelime sayısı)

1= uzunluk = 1 ise (açık), aksi takdirde yanlış

& nerede -> gerçek elemanların indeksi

p in\: belirsiz önekte olup olmadıklarını tüm önekler için belirler

(..)' sağdaki her değere (..) uygulanır (açık önek)

?0,&: -> farklı 0 bitiştirildiği yerde (kelimeleri kendi öneki olarak ele almak için)

p@ dizinleri sembollere dönüştür

x!.. anahtar olarak x (kelimeler) ve .. olarak değerler içeren bir sözlük oluşturma

Şu şekilde okuyun:

  • Anahtar sözcükler ve değerler olarak kelimeler içeren bir sözlük oluşturun ve döndürün.

  • ... farklı konumlardaki (tüm sözcükler) ve açık önek bulunan dizinlerin değerleri

  • ... sadece bir kelimede görünen önekler olarak kesin olarak hesaplanır (her sembolle ilişkilendirilen kelime listesi uzunluğu birdir)

  • ... tüm benzersiz sembollerin karşılık gelen kelimelerle sınıflandırılmasıyla sonuçlanan listeler

  • ... her kelimenin son satırını tekrarlayarak hesaplanan önekler


1

PHP 7.0, 67 bayt (meydan okumayı sonlandırır)

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

komut satırı bağımsız değişkenlerinden girdi alır; sondaki virgül yazdırır; ile çalıştırın -nr.

için yeni PHP , bir bayt ekleyin: Değiştir &aile ""<.

daha eski PHP için şu 70 baytı kullanın:

PHP, 70 bayt

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

1

Brachylog , 23 bayt

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

Çevrimiçi deneyin!

Girdiyi girdi değişkeni aracılığıyla bir liste olarak alır ve çıktı değişkeni aracılığıyla bir çift listesi oluşturur[key, value] . Başka bir giriş dizesinin öneki olmayan herhangi bir girdi dizesi, iki kez kendi başına bir önek olarak oluşturulur, ancak TIO üzerindeki başlık bunun yerine tam listeyi elde etmek için bunu gizler .

 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.

Çıktıdaki kopyalar tolere {}ᵘedilmezse, bir formun kendi öneki olması dışında bırakmanın daha kısa bir yolu yoksa veya ekstra kural olmadan gerekli her çıktı çiftini oluşturmanın dışında, her şeyi sarmak için üç bayt ekleyin ∋gj.
İlişkisiz String


1

APL (Dyalog Klasik) , 38 bayt

Outgolfer Erik Erik'e tek baytlık karakter kodlaması kullanmamı hatırlattığı için teşekkürler

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

Çevrimiçi deneyin!


1
Um ... Burada Adám'ın SBCS'si ile kullanamayacağın kötü karakterlerden birini görmüyorum ...: P
Outgolfer

fark etmeden, tekrar yanlış tercüman versiyonunu seçtim ... bayt sayımı yarıya
indirdiğiniz

0

Python (127)

Bu yüzden @ undergroundmonorail yorum yapamadım, ancak sözlük yaklaşımı almanın daha iyi olacağını düşündüm? Eminim bazı liste / sözlük anlama ile çok muazzam kesilebilir, ama dikte haşhaş ile çalışmak için alınamıyor.

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

Baskı, sözlüğü çıktı sırasına göre çıkarır.

EDIT: Ahh Arabayı kaçırdım: araba / araba: halı kriterleri. Belki bir uzunluk kontrolü?


Belki bir şey eksik, ama bu her karşılaşıldığında alternatif olarak önek girişi eklemek ve silmek gibi görünüyor, bu yüzden 3 kelimede meydana gelirse belirsiz bir önek görünmez?
xnor

0

Harika - 212 karakter

golfed:

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

örnek çıktı:

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
}


0

Zsh , 95 bayt

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

Çevrimiçi deneyin!

Bash / Zsh'de ilişkilendirilebilir bir diziyi "döndürmenin" tek yolu, localanahtar sözcük olmadan bunu bildirmek ve daha sonra üst kapsamda erişmektir. Bu bir bayt tasarruf sağlayacaktır. Ancak, değişkenler aracılığıyla G / Ç genellikle kaşlarını çattığından, bunun yerine dizi tanımını yazdırırız.

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

0

Ruby , 84 bayt

Zaten mevcut bir Ruby çözümü olduğunu fark ettim. Bu, temel olarak daha akıllı bir şekilde önekleri seçerek (sonunda her sözcüğü "önek" olarak ekleme gereğini ortadan kaldırarak) ve değerin üzerine yazmak yerine hash'e eklemeden önce benzersizliği kontrol etmek için önekleri sayarak eski çözümü geliştirir. yinelenen ve sonra girişi silen bir kukla.

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

Çevrimiçi deneyin!

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.