すべての文字が同じ列を検索します


18

私はSOでこの質問に出会い、それが素晴らしいゴルフの挑戦になると思った。だからここにある:

チャレンジ:

文字列のシーケンスを1行に1つずつ読み取り、各文字列が同じ文字を持つすべての位置のリストを出力するプログラムを作成します。

入出力:

入力は、1行以上の印刷可能な非空白ASCII文字で構成され、各行に改行が続きます。すべての入力行が同じ長さであると仮定することができます。改行は入力の一部と見なされません(つまり、一致する文字として出力するべきではありません)。

入力例(SO質問から恥知らずに盗まれた):

abcdefg
avcddeg
acbdeeg

入力を読み取った後、プログラムは一致する各列の位置とそれに含まれる文字を印刷する必要があります。(プログラムは、一致する列がないことを早期に判断できる場合、それ以上の入力の読み取りを停止できますが、する必要はありません。)妥当な出力形式は許可されます。特に、ポジションに0ベースまたは1ベースのインデックスを使用できます。

上記の入力の出力例(0ベースのインデックス付けを使用):

0: a
3: d
6: g

得点:

これはコードゴルフなので、最短の回答が勝ちます。同点の場合、追加の機能に対して小数のタイブレーカー文字が授与される場合があります。

  • -½文字。長さが等しくない入力行を正しく処理します。(出力には、最短の入力行の終わりを超えた位置を含めないでください。)
  • −¼ UTF-8でエンコードされた任意のUnicode文字で構成される入力を正しく処理するための1/4文字。

インスピレーションについては、SOの質問でいくつかの未解決のソリューションを見つけることができます(上記を参照)。

明確化:

  • のように位置と文字を単純に連結しても、「合理的な出力」としてカウントされ0a3d6gませ。出力の各要素を明確に解析できるように、出力の各要素間に何らかの種類の区切り文字(スペースなど)を提供する必要があります。

  • 入力は標準入力ストリーム(stdin)で提供されるか、選択した言語にとって最も自然なテキストファイル入力メカニズムを使用して提供されます。(選択した言語がいない場合は持っているファイル入力のための自然なメカニズムを、精神内の最も近いと思われるものは何でも。)

  • 読み込むデータがなくなると(つまり、ファイルの終わり条件が発生すると)、入力は終了します。必要に応じて、入力を空白行で終了する必要がある場合があります(当然、入力の一部としてカウントしないでください)。そうする場合は、他の人がテストのために正しい入力を提供できるように、回答にそれを記載してください。

  • 最後の行を含むすべての入力行は、改行文字で終わります。あなたの答えは、この改行を一致する列として報告してはいけません。(最後の行が改行で終わらない入力もソリューションで処理できる場合は問題ありませんが、必須ではありません。)


空白行は入力を終了しますか?
スティーブンランバルスキー

「明確に解析できるように、出力の各要素の間に何らかの種類のセパレータを用意する必要があります。」スペースはセパレーターとしてカウントされますか?
スティーブンランバルスキー

@StevenRumbalski:読み込むデータがなくなると入力は終了します。あなたの言語でEOFの検出に問題がある場合、末尾の空白行を許可できると思います。そして、はい、スペースは完全に良いセパレータです。
イルマリカロネン

任意のUTF-8エンコードされたUnicode文字のサンプルコードを入手できますか?
ユーザー不明

回答:


12

APL、25文字

∩/{0=⍴⍵:⍬⋄(⊂⍵,⍨¨⍳⍴⍵),∇⍞}⍞

通訳としてDyalog APL(バージョン13)を使用しました。長さの異なる入力とUnicode(UTF-8)文字の両方を処理します。

例:

      ∩/{0=⍴⍵:⍬⋄(⊂⍵,⍨¨⍳⍴⍵),∇⍞}⍞
abcdefg
avcddeg
acbdeeg

  1 a  4 d  7 g  

      ∩/{0=⍴⍵:⍬⋄(⊂⍵,⍨¨⍳⍴⍵),∇⍞}⍞
test日本
blat日本国foo

  4 t  5 日  6 本 

説明、やや右から左:

  • この答えの主な部分は、中括弧内で定義された直接関数(基本的には匿名関数)です。その正しい引数はで指定されます。
    • 0=⍴⍵:⍬は最初の式であり、空の行を取得したかどうかを確認します(つまり、完了です)。ガード(多くの機能的プログラマーにとって馴染みのある構成)を使用して、コロンの右側の式を条件付きで実行します。この場合、0が正しい引数の形状/長さ()と等しい場合、空のセット()を返します。
    • 関数内の2つの式を区切ります。前の式が評価されなかった(したがって、何も返されなかった)場合、次の式に移動します。
    • 自己参照関数()を使用して、関数を再帰的に呼び出します。関数の引数は、quote-quad()で指定された、評価されていないユーザー入力の行です。
    • ⊂⍵,⍨¨⍳⍴⍵ 文字列内の各文字のペアを作成します。各ペアの最初の要素は文字列内の位置であり、2番目の要素は文字です。
    • ⍳⍴⍵1からのベクトル⍴⍵、または入力文字列の長さを返します。
    • ⍵,⍨¨変換された連結関数(,⍨)を¨、その左(この場合はユーザーの入力)および右の各()要素に適用します。連結関数を交換すると、左右の引数が入れ替わります。
    • 最後に、入力の行を区別できるように、結果をを使用して囲みます。
  • 最初に、関数にユーザー入力()を渡します。
  • 最後に、/交差関数()を使用して、結果のペアのベクトルのベクトルを削減()し、すべてのサブベクトルで見つかったペアを生成します。

正当な理由がないのに、JやGolfScriptにはないAPLを見るたびに、内臓の否定的な反応があります。とにかく優れたソリューションのために+1。
スティーブンランバルスキー

私は実際にJに切り替えることを考えていました...私はそれを私の理由のリストに追加します。:)
ディロン・カウアー


9

J、57 51 44 40文字

,.&.>y;y{{.z[y=.I.*/2=/\]z=.];._2]1!:1]3

私はゆっくりと、しかし確実にそこに着いています。私は思うが、これはまだ理想とはほど遠い。

フックを使用することが答えであると確信しましたが、残念ながらそうではありません(44文字)。

,.&.>((];({{.)~)([:I.[:*/2=/\]))];._2]1!:1]3

短くするには完全に異なる方法が必要な場合があります。


1
+1。しかし、はい、私はJ.から、より良い期待
スティーブンRumbalski

これは私の答えよりも少ない賛成票があるべきではありません。
スティーブンランバルスキー

1
@StevenRumbalskiアップ投票は、常にコードの相対的なサイズを反映するとは限りません。言語の人気コンテストになることもあります。golfscriptの答えはAPLにあるべきだということに同意します。残念なことに、私はすでに投票しており、それをさらに押し上げることはできません。
ガレス

8

Haskell、64文字

main=interact$show.foldl1(filter.flip elem).map(zip[0..]).lines

長さが等しくない行を処理します。Unicodeサポートは、現在のロケール設定に依存します。

出力例:

[(0,'a'),(3,'d'),(6,'g')]

+1。これは私の答えよりも少ない賛成票があるべきではありません。
スティーブンランバルスキー

7

Python 2、スコア81.5(116 94 86 83 82バイト-ボーナス)

import sys
i=0
for x in zip(*sys.stdin)[:-1]:
 i+=1
 if len(set(x))<2:print i,x[0]

素敵なPythonゴルフでは+1ですが、4つの文字をすべて失う可能性があり [:-1]ます。入力の最後に余分な改行を削除しない限り、これは必要ありません(質問には含まれていないようです)。
クリストフ

@ChristopheD:実際、の結果はzip(*sys.stdin)です[('a', 'a', 'a'), ('b', 'v', 'c'), ('c', 'c', 'b'), ('d', 'd', 'd'), ('e', 'd', 'e'), ('f', 'e', 'e'), ('g', 'g', 'g'), ('\n', '\n', '\n')]。改行の最後のタプルを削除しないようにする方法がわかりません。誤解した場合は修正してください。賛辞をありがとう。
スティーブンランバルスキー

あなたは、データファイルの最後の改行を削除する場合はその行のタプルが完了していない(ミス1「\ n」のようにジップのみ考慮しての除去を可能に我々が探しているリターンデータ、[:-1]例えばzip([1,2,3,4],[1,2,3])=> [(1, 1), (2, 2), (3, 3)]
ChristopheD

@ChristopheD:仕様ごとに、「入力は[...]行[...]で構成され、各行の後に改行が続きます。」
イルマリカロネン

1
この答えを下した人はその理由を説明しますか?
スティーブンランバルスキー

5

(Bash)シェルスクリプト、105文字

誰かがこれについていくつかのトリックをお持ちの場合は、コメントに自由に記入してください!

for((i=1;i<`tail -1 $1|wc -c`;i++))do
x="cut -c$i $1";y=`$x`;[ `$x|uniq|wc -l` = 1 ]&& echo $i ${y:3};done

結果:

1 a
4日
7グラム

これを機能させるのに問題があります。サンプル入力でこれを実行すると、/tmp/cols.sh: line 2: [1: command not found他のエラーなどの一連のエラーが出力されます。
イルマリカロネン

@Ilmari Karonen:これはMac(Snow Leopard、10.6.2)でテストされましたが、他の場所で動作するはずです。明日、Linuxで修正する予定です(小さな修正が必要です)
ChristopheD

2
ormaajには担当者がいませんでしたが、コメントしたかったの[です。また、$ {y:3}は、正確に3行の入力でのみ機能します。yields(100文字)while((++i%`tail -1 $1|wc -c`));do x=`cut -c$i $1`;((`uniq|wc -l`==1))<<<"$x"&&echo $i ${x: -1};doneを修正して最適化し、デフォルト値を使用すると、もう1つ保存できますfor((;++i<`tail -1 $1|wc -c`;))doが、bashには未修正のバグがあります。
ピーターテイラー

4

Perl、87文字(-½文字タイブレークボーナス)

SOスレッドから私自身のソリューションのゴルフバージョンを以下に示します

chomp($a=$b=<>);$a&=$_,$b|=$_ for<>;@$_=$$_=~/./sgfor a,b;$b[$i++]eq$_&&say"$i:$_"for@a

SOバージョンとは異なり、このバージョンでは出力に1ベースのインデックスが使用されます。Perl 5.10 say機能を使用するため、perl -M5.010(またはperl -E)で実行する必要があります。

SOバージョンと同様に、このコードは可変長の行処理し、標準入力と出力がUTF-8モードの場合、任意のUnicode入力処理します。残念なことに、デフォルトでは、フリーではない -CSコマンドラインスイッチを指定しない限り、そうではありません。したがって、-½のボーナスは獲得できますが、-¼のボーナスは獲得できません。

編集: 1 charがバグを修正するには:入力文字列は、彼らがに終わることができないという意味ではありませんラインフィードが含まれていないという理由だけで$a(例えば"+" & "J" eq "\n")。


1
chop代わりにを使用して1文字を保存できますchomp
トト

@ M42:良い点ですが、私は現在のバージョンの堅牢性が好きです。mとりあえずこれを続けると思いますが、現時点でランキングに違いが出るわけではありません。:)
イルマリカロネン

3

T-SQL

SELECT N.number, letter = MIN(SUBSTRING(L.line, N.number, 1))
FROM Lines AS L
INNER JOIN master.dbo.spt_values AS N ON N.type = 'P'
WHERE N.number BETWEEN 1 AND (SELECT MAX(LEN(L2.line)) FROM Lines AS L2)
GROUP BY N.number
HAVING COUNT(DISTINCT SUBSTRING(L.line, N.number, 1)) = 1
ORDER BY N.number

2

Scala 115 107:(UTF-8を処理するための¼)

io.Source.stdin.getLines.map(_.zipWithIndex).toList.flatten.groupBy(_._2).map(_._2.toSet).filter(_.size==1)

テストされていないため、Source.fromFile ("f")代わりにstdin

io.Source.fromFile ("f").
  getLines.map (_.zipWithIndex).
    toList.flatten.groupBy (_._2). 
      map (_._2.toSet).
        filter (_.size==1)

結果:

List(Set((a,0)), Set((g,6)), Set((d,3)))

を使用してサイズ8を縮小してくれたGarethに感謝しstdinます。


8文字を保存するstdin代わりに使用できませんfromFile("f")か?
ガレス

2

VBA(307.25 284-0.75ボーナス= 283.25)

私はこれがすでに勝ち取っていることを知っていますが、ここに私のショットがあります(ファイルを読み取らず、文字列だけを読みます-ioを追加する必要があります)。l()再帰的に使用できるようになりました。通常、実際のプログラミングを再帰する必要はありません。私はあまりテストしませんでしたが、これはユニコードのボーナスポイントの規定をカバーしていると思います。またvbCr、ラインターミネータを想定しています。そのため、これがすべてのシステムに変換されるわけではありません。

コード:

Function a(i)
b=Split(Left(i,Len(i)-1),vbCr):c=UBound(b):For q=1 To Len(b(c)):d=Mid(b(c),q,1):If l(b,c,q,d) Then a=a & q & ": " & d & vbCr:Next
End Function
Function l(m, n, o, p)
If n+1 Then l=IIf(o<=Len(m(n)),Mid(m(n),o,1)=p,0) And l(m,n-1,o,p) Else l=Mid(m(n+1),o,1)=p
End Function

入出力の例:

Debug.Print a("abcdefghijklmnop" & vbCr & "abcdefg" & vbCr & "abcabcghijkl" & vbCr)

1: a
2: b
3: c
7: g

2

Q、32

{a!((*:)x)a:(&)1=(#:')(?:')(+)x}

使用法

q){a!((*:)x)a:(&)1=(#:')(?:')(+)x}[("abcdefg";"avcddeg";"acbdeeg")]
0| a
3| d
6| g

K、22

上記のソリューションは、KインタープリターにK関数を渡すのではなく、完全にKで記述することで22に減らすことができ、必要な括弧の数を減らすことができます。

{a!@[*x]a:&1=#:'?:'+x}

1

PHP、123 127 :(

私はそれに満足していません(改善されるはずです)が、ここに行きます:

<?$a=$b=trim(fgets(STDIN));while($l=fgets(STDIN)){$a&=$l;$b|=$l;}$n=-1;while(@$a[++$n]){echo$a[$n]!=$b[$n]?'':"$n:{$a[$n]}\n";}

それが機能する証拠。

誰かが$ aと$ bを初期化するより賢い方法を考えられるなら、私に知らせてください。元々私は持っていた$a=$b=$n=''[empty] & [anything] == [empty]、最終的には$ bは正しかったが、$ aはコンテンツを持っていなかった。


編集:改行処理を修正する必要がありました(+6)が、終了タグを削除しました(-2)。


私は興味があります、なぜあなたはあなたの答えコミュニティwikiのほとんどを作りますか?
ガレス

私はこれをするつもりはなかった。ずっと前に私がCodeGolfに初めて参加したとき、誰かがそれが標準だと言っていました。習慣を破る必要があります。ただし、今ではウィキを解除できます。 codegolf.stackexchange.com/a/2249/1419(コメントを参照)
ラマ氏

私はそれがコードゴルフの質問のためにSOで物事を行う標準的な方法だったと思いますが、ここではそうではありません。:
ガレス

おそらくそれらにフラグを立てて、モデレーターにCWを解除するよう依頼することができます。間違いだったと説明してください。
イルマリカロネン

を省略すると、2つの文字を保存できます?>。ただし、コードにバグがあることに気付きました。すべての行に指定された末尾の改行が含まれている場合、余分な一致が出力されます。
イルマリカロネン

1

JavaScript(125 134 140

for(i=s=[];I=s[++i]=prompt(o='');S=I);for(c=-1;w=r=++c<S.length;o+=r?c+':'+C+'\n':'')for(C=S[c];w<i;)r&=s[w++][c]==C;alert(o)

デモ:http : //jsfiddle.net/Fv7kY/4/

編集1:中括弧を避けるためにループを再配置します。[]と組み合わせてiを初期化しsます。w式に増分を移動します。

編集2S=I最後に入力した単語をキャプチャし、を使用して保存するように設定しs[1]ます。と結合r=1++c<S.lengthます。C=s[c]内側のループに設定しC、前と次の単語の代わりに比較して、式s[w][c]==s[w++][c]をちょうどに短縮しますs[w++][c]==C。合計9文字を保存しました。またw=r=...、それが真でw=1ある場合、これは初期化wする必要があるためです。


1

ルビー(71)

a,*s=*$<.lines
(a.size-1).times{|i|s.all?{|t|t[i]==a[i]}&&p([i,a[i]])}

出力:

[0, "a"]
[3, "d"]
[6, "g"]

注:Ruby 1.9が必要なようです。Ruby 1.8との互換性のために、に置き換えt[i]てくださいt[i,1]
イルマリカロネン

1

Common Lisp、183 165文字

(let((l(loop for m =(read-line)until(equal m "")collect m)))(loop for c across(car l)for i from 0 if(null(remove c(mapcar(lambda(y)(char y i))l)))collect(list i c)))

読み取り可能な形式:

(let ((l (loop for m = (read-line) until (equal m "") collect m)))
  (loop for c across (car l)
        for i from 0 
        if (null (remove c 
                         (mapcar (lambda(y) (char y i))l)))
        collect(list i c)))

これをREPLに直接入力し、空の行で終了する行を入力します。


1

C、126文字

char a[999],b[999];main(i){for(gets(a);gets(b);)for(i=0;b[i];++i)a[i]^b[i]?a[i]=0:0;
while(i--)a[i]&&printf("%d:%c\n",i,a[i]);}

私はこれを見つめてきましたが、小さくすることはできません。新しいアプローチが必要になる場合があります。

(ボーナスポイントはありません。最初の行が短い場合にのみ、異なるサイズの行を処理します。)


0

.NET 4を使用したC#(280)

using c=System.Console;class P{static void Main(){char[]a=c.ReadLine().ToCharArray();int r,i,l=a.Length;m:i=0;n:r=c.Read();if(r>0&&r!=10&&r!=13){if((int)a[i]!=r)a[i]='\0';i++;goto n;}for(;i>0&&i<l;)a[i++]='\0';if(r>0)goto m;for(i=0;i<l;i++)if(a[i]!='\0')c.WriteLine(i+":"+a[i]);}}
  • 1行、280文字
  • 必要なすべてのusingステートメントとMainメソッドが含まれます。
  • プログラム最後に空行を必要としませんが、受け入れます
  • 空行は無視されます
  • 任意の長さの入力文字列を処理します。
  • 出力を最後まで予約します(一方、元の回答は増分出力を提供しました)

読みやすいバージョン

    char[]a=c.ReadLine().ToCharArray();
    int r,i,l=a.Length;
    m:
    i=0;
    n:
    r=c.Read();
    if(r>0&&r!=10&&r!=13){
        if((int)a[i]!=r)
            a[i]='\0';
        i++;
        goto n;
    }
    for(;i>0&&i<l;)
        a[i++]='\0';
    if(r>0)
        goto m;
    for(i=0;i<l;i++)
        if(a[i]!='\0')
            c.WriteLine(i+":"+a[i]);

元の答え

using c = System.Console; class P {static void Main(){char [] a; var b = c.ReadLine(); a = b.ToCharArray(); while(b!= ""){for(int i = 0; i

  • 1行
  • 207文字
  • 必要なすべてのusingステートメントとMainメソッドが含まれます。
  • 空行が入力されると、プログラムは終了します。
  • 最初よりも短い入力文字列を処理しません。


読み取り可能なバージョン:

    static void Readable()
    {
        char[]a;
        string b=System.Console.ReadLine();
        a=b.ToCharArray();
        while(b.Length>0)
        {
            for (int i = 0; i < a.Length; i++)
            {
                if (a[i] != b[i])
                {
                    a[i] = '\0';
                }
                else
                {
                    System.Console.WriteLine(i+": "+a[i]);
                }
            }
            b=System.Console.ReadLine();
        }
    }


チャレンジのテスト入力でこれを実行すると、が表示されます0: a 1: b 2: c 3: d 4: e 5: f 6: g 0: a 2: c 3: d 6: g 0: a 3: d 6: g。予想される出力はになります0: a 3: d 6: g
イルマリカロネン

@Ilmari OK、しかし、各入力行の後に同じ列/文字を出力します。ファイルを標準入力として供給している場合、出力は奇妙に見えるかもしれませんが、手動で入力する場合、それは理にかなっていると思います。ただし、リファクタリングの方法を検討します。
ウィリー博士の見習い

いずれかの行が最初の行より長い場合、ソリューションはクラッシュします。
ティムウィ

@Timwi Ah ...それを指摘してくれてありがとう!
ウィリー博士の見習い

0

python 122文字

print("\n".join([str(i)+':'+str(x[0]) for i,x in enumerate(zip(*[tuple(x) for x in input().split()])) if len(set(x))<2]))

あなたは、間にスペースを必要としない)for。だから、代わりに…str(x[0]) for i,x…、あなたがすることができます…str(x[0])for i,x…。それはまたで立ち上がるtuple(x) for.split()])) if
Cyoce

-1

ルビー(242)

s = %w{ abcdefg avcddeg acbdeeg aejdjeggd }
cols = []
s.sort{ |a, b| b.size <=> a.size }[0].size.times do |i|
  uneq=true
  l = s[0][i]
  s.each { |w| uneq = false if l != w[i] }
  cols << [l, i] if uneq
end
cols.each { |c| puts c.join('|') }

課題の目的は、標準入力から行を読み取ることでした。私は、その概念は実際には存在しないが、RubyにはあるSTDINARGFまたは単にプレーンなgets)言語(ブラウザー内JavaScriptなど)のスラックをいくらか減らしたいと思っています。
イルマリカロネン

うん、いいよ。しかし、STDINが1行を受け入れると考えると、「別の行に入力するか、停止するには 'n'」のようなものを想定するのでしょうか?したがって、配列を構築するループを作成します。
-agmcleod

質問にいくつかの説明を追加しました。基本的に、ファイルの終わりに達するまで入力行を読み続ける必要があります。
イルマリカロネン

大量の不要な空白があります。
チョイス16

-1

C#

List<string> strings = new List<string> { "abcdefg", "avcddeg", "acbdeeg", "aejdjeggd" };
var transposes = from index in Enumerable.Range(0, strings.First().Length)
                 select new string((from s in strings select s[index]).ToArray());
int i = 0;
foreach(string transpose in transposes)
{
   if (transpose.Distinct().Count() == 1)
     Console.WriteLine("{0}: {1}", i , transpose[0]);
   i++;
}

1
こんにちは、Arjang、codegolf.SEへようこそ!あなたの答えに対するいくつかのコメント:最初に、これはコードゴルフの挑戦であるので、あなたはあなたのソリューションをできるだけ短くすることを試みることが期待されています。はじめに、単一の文字に簡単に短縮できる長い変数名と、削除できる余分な空白があります。(「ゴルフ」と一緒にコードの読み取り可能なバージョンを投稿することは問題ありませんが、実際にはゴルフソリューションも投稿する必要があります。)次に、質問を注意深く読んだ場合は、標準入力から文字列を読むことを指定しました、ハードコードではありません。
イルマリカロネン
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.