文字列セットの明確なプレフィックスをすべて検索する


12

この課題には、RubyのAbbrevモジュールをできるだけ少ないコードで実装する必要があります。

チャレンジ

  • 入力は、文字列の配列(配列、リスト、シーケンスなど)として言語が持つものです。関数を記述することも、STDINでコンマ区切りの単語を受け入れることもできます。

  • 次に、これらの文字列の明確なプレフィックスのセットを計算する必要があります。これは、略語のハッシュ(またはマップ、オブジェクトなど)を元の文字列に返す必要があることを意味します。

    • 「プレフィックス」は、文字列の先頭から始まる元の文字列の部分文字列です。たとえば、「pref」は「prefix」という単語のプレフィックスです。

    • 明確なプレフィックスは1ワードのみを意味することができるものです。あなたの入力がある場合たとえば、car,cat、その後、caそれは「車」またはいずれかを意味する可能性があるため、明確な接頭辞ではありません「猫。」

    • この規則の例外は、単語は常にそれ自身の接頭辞であるということです。たとえば、次のような入力を持っている場合はcar,carpet、car:carあなたの出力でなければなりません。

  • その後、hash / map / object / etcを返すことができます。あなたの関数から(またはあなたの言語で同等のことをする)、またはkey:valueの形式でペアでSTDOUTに出力しますf:foo,fo:foo,...。(キーと値のペアは、コードを短くする場合、空白文字で区切られることもあります。)

テストケース

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

ルール

  • 入力には重複した要素は含まれません。

  • 出力の順序は任意です。ソートする必要はありません。

  • AbbrevRubyのような組み込みのモジュール/関数/ものを使用することはできません。

  • これはなので、バイト単位の最短コードが勝ちます!


stdoutは正確にその形式である必要がありますか?それともkey:value\nkey:value\nkey:value…?
— 地下

4
略語という言葉を再定義するのではなく、標準的な意味の接頭辞を使用するだけです。そして、私は最初の直感は入力語ごとに1つの接頭辞だけが必要だったということより、曖昧さのないことはキーの望ましい特性をuniqueよりも効果的に伝えると思います。
— ピーターテイラー

@PeterTaylorいい考えです。編集しました。
— ドアノブ

1
同じキーを複数回(同じ値で)印刷できますか?
— xnor

回答:


1

APL(46)

(はい、APL文字セットは1バイトに収まり、余裕があります。)

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

これは、文字列のリストを取得し、2行N列の行列を返す関数です。各行には、明確なプレフィックスとそれが属する単語が含まれます。

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

説明:

  • ∆←⍵:正しい引数を格納します ∆ます。
  • {↑∘⍵¨⍳⍴⍵}¨∆:の各要素 ∆、その要素の可能なプレフィックスを取得します。
    • ⍳⍴⍵:リスト1の長さから⍵
    • ↑∘⍵¨:これらの数値のそれぞれについて、から多くの要素を取得し⍵ます。
  • ∪⊃,/:リストを連結し、一意の値を取得します。
  • {... }¨:一意のプレフィックスごとに:
    • ∆/⍨⊃¨⍵∘⍷¨∆:その接頭辞で始まる単語を選択します
    • (⊂⍵),:プレフィックスも囲み、連結します
    • ∆/⍨2=⍴∆←:2つの要素(接頭辞と一致する1つの単語)がある場合にのみリストを返します
  • ↑:タプルのリストを行列に変換します

リンクは現在壊れています
— ...-user202729

3

Pythonの2.7 - 146の 141バイト

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行目と5行目のインデントは4スペースではないことに注意してください。これは、SEのマークダウンインタープリターの副作用です。これはリテラルのタブ文字なので、1バイトのみです。

これは技術的には仕様ではありませんが、Doorknobで明確になったら変更します。出力を区切るために、コンマの代わりに改行を使用します。例えば:

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

New:チェックする文字列を変数に割り当てることで、5文字を取り除くことができましたe。つまりe、w[:a]3回入力するのではなく、入力するだけで済みます。また、を実行してe=w[:a+1]に変更...range(1,len(w)+1)することでキャラクターを保存しrange(len(w))ます。


説明:

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.

sum(b.startswith(e) for b in l)代わりに使用できますlen(filter(lambda b:b.startswith(e),l))
— ニクラス

またはに短縮b.startswith(e)して、の代わりにカウントを確認することもできます。b.find(e)==0b[:a+1]==e<2==1
— XNOR

またやるe=""\n for a in w:\n\te+=a代わりにfor a in range(len(w)):\n\te=w[:a+1]、それは10文字セーブとして
— WorldSEnder

私は必要とする人のためにここにungolphedバージョン作った gist.github.com/stuaxo/c371b2d410191a575b763b74719856c8を
— スチュアートアクソン

3

J-47文字

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

Jは文字列を単なる文字のベクトルとみなします。つまり、文字列のリストを作成しようとすると、実際には文字のテーブルが作成されるため、末尾にスペースが埋め込まれます。これに対するJの解決法はboxと呼ばれるため、この関数は引数として文字列のボックス化されたリストを取り、長さを保持します。

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

また、Jにはハッシュタイプがないため、それに最も近いのは、たとえばボックス化された文字列など、2列のアイテムのテーブルです。それが受け入れられず、デフォルトでキーと値の形式にする必要がある場合、合計67文字でこの形式に出力を再フォーマットできます。

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

爆発による説明:

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

例:

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

ハスケル 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]

ゴルフされていないバージョン:

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

例:

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

initsリスト/文字列のすべてのプレフィックスを検索する関数を使用しました。不正行為としてカウントされますか?


1
あなたは置き換えることができますconcatMapによって(=<<)プレリュードです。10文字節約します。
— ライモイド

@Rhymoidありがとうございます。削除しましたconcatMapが、9文字以上保存できません。
— lortabac

ああ待って、あなたは正しい。Haskellは>>=\ 、単一の語彙素と見なします。申し訳ありませんがそのことについて...
— 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]

入力内の各単語の接頭辞を反復処理し、対応する接頭辞/単語のペアが1回だけ出現する場合、または単語全体に出現する場合に出力します。これらの条件の1つが満たされた場合にのみ印刷するためのor(およびprint関数である)の短絡動作を利用します。

whileループを繰り返したときに、空の文字列が残っ終了し、短くプレフィックスを作成するための最後の文字を遮断します。これが、インデックスを作成するか、何かにスライスする唯一の時間です。

e元のコンマ区切りの入力文字列Sでsubstringsを検索することで、入力内のプレフィックスの出現をカウントします','+e。入力文字列の前にコンマを追加します。この追加により、の場合、余分な空の文字列要素splitが生成されますが、空ではない部分文字列がないため、効果はありません。

部分文字列eが単語全体である場合をチェックするために、文字w列比較演算子を使用してそれらを比較します。これは辞書式に比較されるため、短いプレフィックスは小さくなります。e==wまたはの場合、二重比較は失敗しますS.count(c+e)<2。

フォームでの出力の印刷e,wが許可されている場合、e+c+w代わりに書き込みで文字を保存します。

功績undergroundmonorailからその答えは、私は私の全体的なコード構造をベース。


(e<w)*S.count(c+e)>1e<w<w*S.count(c+e)2人のキャラクターを救うためにゴルフすることができます。
— isaacg

@isaacgありがとう!最適化を追加しました。
— xnor

1

ルビー、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

ゴルフをしていない:

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)

特にゴルフではありません。私はそれが短くなると確信しています

J implとかなり似ています。上記のように、基本的にはすべての(適切な)接頭辞を収集し、接頭辞から単語を削除して("car"/ "carpet"ケースを処理する)、それらを等価クラスにグループ化し、1つの要素のみを持つクラスを選択し、リストからそれらを減らします文字列、および文字列からそれ自体へのマップの追加。

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

いくつかのテストケース

ノートという点で、k/ q、唯一の単一文字のニーズを含む文字列は、単項使用してそのようにマークされるので、文字列は、文字のリストである,機能を、&mmwrt単一の文字列のみを含む文字列のリスト

これらの使用qのshow内蔵されていた結果を読みやすくするために、いくつかのデータ構造のための書式設定機能、:

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

初期ゴルフ。

入力:

code,golf,going

出力:

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


1

Perl、93 77

読みやすくするために改行とインデントを使用:

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

少し遅すぎて長すぎますが、ようやく100未満になったことがうれしいです。関数はハッシュ変数に割り当てることができるリストを返します。

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

そして

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

実際には、返されたリストはまだフィルター処理されていません-ハッシュの構築は、割り当ての時点、つまり関数の外で完了しています。IFそれがきれい/フェア十分ではありません、先頭に追加し、中括弧の中にカウントするために3を追加し、プット機能の内容+、関数を返す「真」のハッシュリファレンスを- 。


1

Q:44バイト

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

ノート

  • Q言語には、内部的にK4という名前の内部コアがあります(この回答およびこの質問に対する以前の別の回答で使用されます)

  • コードをテストするには、インタープリターをダウンロードします(kx.com、非商用利用は無料、Windows、Linux、Macのサポート)

通訳者は2つの構文を認めています:

  • 詳細(読みやすい名前、moandとdiadの異なる名前、より多くのライブラリ、...)。拡張子がqのソースファイルまたはインタラクティブインタープリターを読み込む

  • コンパクト(機能的な内部コア、1文字の演算子、両方に同じ文字がmonad / diadを使用、...)。k拡張子のソースファイル、またはkモードの対話型インタープリターを読み込みます(プロンプトで\を書き込みます)。このモードでコードをテストする必要があります

コードは、ラムダ(無名関数)を定義します。関数に名前を付けるには、プレフィックス名:(ex f:{..})が必要なので、46バイトが必要です

テスト

(名前付き関数を想定:それ以外の場合は、コードをfに置き換えます)

f `code`golf`going

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

辞書を返します(構文キー!値)。キーはシンボルのリスト( `symb`symb ..)であり、値はシンボルのリストのリストです。インタラクティブインタープリターでsententeを実行すると、より便利なプレゼンテーションが得られます(各キーと関連付けられた値は異なる行にあります)

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

説明

x ラムダへの暗黙の引数です

$x 記号リストを文字列リストに変換します

(-1_)\ シンボルリストの各要素を反復処理します

(各文字列については、プレフィックスを計算します(eatの繰り返しでは、空の文字列になるまで、文字列の最後の文字(-1_)が削除されます))

$ 再びシンボルリスト(すべてのプレフィックスのリスト)に変換します

p: そしてpに代入します

,/ すべてをレイズします(連結して1レベルの構造を作成します)

= classify->一意のプレフィックスごとに、対応する単語を関連付けます

#:' 長さ(各プレフィックスに関連付けられている単語の数)を計算します

1= length = 1(明確)の場合はtrue、そうでない場合はfalse

& ここで->真の要素のインデックス

p in\: 明確な接頭辞にある場合、すべての接頭辞を決定します

(..)' 右側の各値に適用(..)(明確なプレフィックス)

?0,&: ->個別の0が連結された場所(単語をそれ自体の接頭辞として扱うため)

p@ インデックスをシンボルに変換します

x!.. x(単語)をキーとして、..を値として辞書を作成します

として読む:

  • 単語をキーとして、値を含む辞書を作成して返します。

  • ...明確な位置0(すべての単語)および明確なプレフィックスのインデックスの値

  • ... 1つの単語にのみ現れるプレフィックスとして計算された明確な計算(各シンボルに関連付けられたワードリストの長さは1です)

  • ...すべての一意のシンボルを対応する単語で分類した結果のリスト

  • ...各単語の最後の文字をドロップすることを繰り返して計算されたプレフィックス


1

PHP 7.0、67 バイト(チャレンジ後)

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

コマンドライン引数から入力を受け取ります。末尾のコンマを出力します。で実行し-nrます。

以下のための新しいPHP、1つのバイトを追加します交換してください&aと""<。

古いPHPの場合、これらの70バイトを使用します。

PHP、70バイト

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

1

Brachylog、23バイト

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

オンラインでお試しください!

入力を入力変数のリストとして受け取り、出力変数のペアのリストを生成し[key, value]ます。別の入力文字列のプレフィックスではない入力文字列は、それ自体のプレフィックスとして2回生成されますが、TIOのヘッダーᵘは、ᶠます。

 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.

出力内の重複が許容されない場合、3バイトを追加して全体をラップします{}ᵘ。ただし、それ自体のプレフィックスであるフォームを除外するか、余分なルールなしで必要なすべての出力ペアを生成する短い方法がない限り∋gj。
— 関連のない文字列


1

APL(Dyalog Classic)、38バイト

シングルバイト文字エンコーディングの使用を思い出させてくれたErik the Outgolferに感謝します

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

オンラインでお試しください!


1
うーん...私は...あなたがここにアダムのSBCSと一緒に使用しないことを悪い文字のいずれかが表示されない:P
— エリックOutgolfer

気付かずに、間違ったインタープリターバージョンを再度選択しました...バイトカウントを半分にしてくれてありがとう:)
— ngn

0

Python(127)

だから私は@undergroundmonorailにコメントすることはできませんでしたが、辞書的なアプローチを取る方が良いと思いましたか?リスト/辞書の理解があれば、それも大幅に削減できると確信していますが、辞書からポップすることで機能させることはできません。

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

印刷は辞書を順不同で出力します。

編集:ああ、私は車:車/車:カーペットの基準を逃した。たぶん長さチェック?


何かが足りないかもしれませんが、これは遭遇するたびにプレフィックスエントリを交互に追加および削除するようですので、3ワードで発生した場合、あいまいなプレフィックスは表示されませんか?
— xnor

0

Groovy-212文字

ゴルフ済み:

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

出力例:

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

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

ゴルフをしていない:

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バイト

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

オンラインでお試しください!

Bash / Zshで連想配列を「返す」唯一の方法は、localキーワードなしで宣言し、親スコープでアクセスすることです。これにより、1バイト節約できます。ただし、変数を介したI / Oは一般的に嫌われているため、代わりに配列定義を出力します。

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

ルビー、84バイト

既に既存のRubyソリューションがあることに気づいただけです。これは基本的に古いソリューションを改善します。よりスマートな方法でプレフィックスを選択し(末尾に「プレフィックス」として各単語を追加する必要がなくなります)、プレフィックスをカウントしてハッシュに追加する前に一意性を確認し、値を上書きする代わりに重複がある場合はダミー、その後エントリを消去します。

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

オンラインでお試しください!

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.