FizzBu​​zzリバースソルバー


32

概要:一般化されたFizzBu​​zzプログラムの出力が与えられると、プログラムに使用される要因と単語のリストを返します。

チャレンジの説明

使用する要素と単語のリスト、および開始する数を入力として取り込む一般化されたFizzBu​​zzプログラムを想像してください。たとえば、このプログラムの入力が

3 2,Ninja 5,Bear 7,Monkey

プログラムから番号をプリントアウトするだろう3100割り切れる数字に置き換える、2Ninja、数字が割り切れる5Bear、数字がで割り切れる7Monkey。割り切れる数の場合、それらの用語の複数の場合、プログラムは、単語を連結し、NinjaBearor BearMonkeyNinjaMonkeyorなどの内容を出力しNinjaBearMonkeyます。その入力の出力は次のとおりです。

3
Ninja
Bear
Ninja
Monkey
Ninja
9
NinjaBear
11
Ninja
13
NinjaMonkey
Bear
Ninja
17
Ninja
19
NinjaBear
Monkey
Ninja
23
Ninja
Bear
Ninja
27
NinjaMonkey
29
NinjaBear
31
Ninja
33
Ninja
BearMonkey
Ninja
37
Ninja
39
NinjaBear
41
NinjaMonkey
43
Ninja
Bear
Ninja
47
Ninja
Monkey
NinjaBear
51
Ninja
53
Ninja
Bear
NinjaMonkey
57
Ninja
59
NinjaBear
61
Ninja
Monkey
Ninja
Bear
Ninja
67
Ninja
69
NinjaBearMonkey
71
Ninja
73
Ninja
Bear
Ninja
Monkey
Ninja
79
NinjaBear
81
Ninja
83
NinjaMonkey
Bear
Ninja
87
Ninja
89
NinjaBear
Monkey
Ninja
93
Ninja
Bear
Ninja
97
NinjaMonkey
99
NinjaBear

プログラムが単語を結合する必要があるときはいつでも、常に最小の数値から最大の数値に変化することに注意してください。したがって、次のようなものは出力されませんMonkeyBear(MonkeyはBearよりも大きいため)。

あなたのプログラムがでとるべき出力として一般FizzBu​​zzプログラムの入力、および出力入力一般FizzBu​​zzプログラムに与えられています。つまり、一般化されたFizzBu​​zzプログラムの「逆プログラム」を作成します。たとえば、上記のコードブロックを入力として指定すると、プログラムはを出力します3 2,Ninja 5,Bear, 7,Monkey

言葉は常に続くいくつかのルールがあります:

  • 入力から要因や単語が何であるかを正確に伝えることは常に可能です。
  • 各単語は大文字で始まり、他の大文字または数字は含まれません。
  • 各要因は一意です。

サンプルの入力と出力

入力:

Calvins
7
Hobbies
9
10
11
Calvins
13
14
15
Hobbies
17
Calvins
19
20
21
22
23
CalvinsHobbies
25
26
27
28
29
Calvins
31
Hobbies
33
34
35
Calvins
37
38
39
Hobbies
41
Calvins
43
44
45
46
47
CalvinsHobbies
49
50
51
52
53
Calvins
55
Hobbies
57
58
59
Calvins
61
62
63
Hobbies
65
Calvins
67
68
69
70
71
CalvinsHobbies
73
74
75
76
77
Calvins
79
Hobbies
81
82
83
Calvins
85
86
87
Hobbies
89
Calvins
91
92
93
94
95
CalvinsHobbies
97
98
99
100

出力:

6 6,Calvins 8,Hobbies

入力:

FryEggman
7
Am
Fry
The
11
FryAmEggman
13
14
FryThe
Am
17
FryEggman
19
AmThe
Fry
22
23
FryAmEggman
The
26
Fry
Am
29
FryTheEggman
31
Am
Fry
34
The
FryAmEggman
37
38
Fry
AmThe
41
FryEggman
43
Am
FryThe
46
47
FryAmEggman
49
The
Fry
Am
53
FryEggman
The
Am
Fry
58
59
FryAmTheEggman
61
62
Fry
Am
The
FryEggman
67
Am
Fry
The
71
FryAmEggman
73
74
FryThe
Am
77
FryEggman
79
AmThe
Fry
82
83
FryAmEggman
The
86
Fry
Am
89
FryTheEggman
91
Am
Fry
94
The
FryAmEggman
97
98
Fry
AmThe

出力:

6 3,Fry 4,Am 5,The 6,Eggman

入力:

DeliciousTartApplePie
DeliciousCreamPancakeStrawberry
DeliciousProfiterole
DeliciousCream
DeliciousPancake
DeliciousCreamStrawberryTart

出力:

95 1,Delicious 2,Cream 3,Pancake 4,Strawberry 5,Tart 19,Apple 95,Pie 97,Profiterole

ここで入力の生成に使用したコードを取得できます


リストは常に正確に100になりますか?
デニス

@Dennisはい、上限は常に100です。-
アブサン

15
あなたの例の1つであることは名誉です。
NinjaBearMonkey

これは、もともとサンドボックスにあったものよりもはるかに優れたチャレンジのバージョンです:)
ベータ崩壊

1
@NinjaBearMonkey名前に多くの単語を含めると、より良い例になります。@Pyrrhaも含めてくれてありがとう!:)
FryAmTheEggman

回答:


10

Pyth、73バイト

jd+J-101lK.zjL\,Sm,_-F>2+_Jf}d@KTUKd{smtcdf-@dTGUdf>T\:K

それは確かに厳しいものでした。@MartinBüttnerの例のすべてを含むすべてのエッジケースと、リピートファクターなしの例を取り上げたと思います。

NinjaBearMonkeyおいしさ

高レベルでは、プログラムは最初に大文字のアルファベット文字列を切り刻んですべての単語を見つけます。

次に、各文字列が行に表示されるかどうかに応じて行がマッピングされ、考えられる各要素がテストされて、同じ順序が生成されるかどうかが確認されます。存在する場合、因子はgobalリストに追加されます。このリストでは、因子がすでに存在しているかどうかが確認されます。まだ存在していない場合、係数が使用されます。文字列は、入力の最初の出現順に並べられます。これにより、同じ行に1回だけ出現する文字列の順序が明確になります。

その後は、フォーマットと印刷だけです。


5

Scala、350文字

(s:String)⇒{def g(a:Int,b:Int):Int=if(b==0)a.abs else g(b,a%b);val(j,q)=(s.lines:\100→Map.empty[String,Int]){case(l,(n,m))⇒if(l(0).isDigit)(n-1,m)else(n-1,m++(Seq(Seq(l(0)))/:l.tail){case(x,c)⇒if(c.isUpper)Seq(c)+:x else (x(0):+c)+:x.tail}.map{t⇒val w=t.mkString;w→g(m.getOrElse(w,n),n)})};s"${j+1}"+q.map{case(k,v)=>s" $v,$k"}.toSeq.sorted.mkString}

勝っていない...しかし素晴らしい質問。

テスト結果:

scala> (s:String)⇒{def g(a:Int,b:Int):Int=if(b==0)a.abs else g(b,a%b);val(j,q)=(s.lines:\100→Map.empty[String,Int]){case(l,(n,m))⇒if(l(0).isDigit)(n-1,m)else(n-1,m++(Seq(Seq(l(0)))/:l.tail){case(x,c)⇒if(c.isUpper)Seq(c)+:x else (x(0):+c)+:x.tail}.map{t⇒val w=t.mkString;w→g(m.getOrElse(w,n),n)})};s"${j+1}"+q.map{case(k,v)=>s" $v,$k"}.toSeq.sorted.mkString}
res0: String => String = <function1>

scala> res0("""DeliciousTartApplePie
     | DeliciousCreamPancakeStrawberry
     | DeliciousProfiterole
     | DeliciousCream
     | DeliciousPancake
     | DeliciousCreamStrawberryTart""")
res1: String = 95 1,Delicious 2,Cream 3,Pancake 4,Strawberry 5,Tart 95,Apple 95,Pie 97,Profiterole

scala> res0("""FryEggman
     | 7
     | Am
     | Fry
     | The
     | 11
     | FryAmEggman
     | 13
     | 14
     | FryThe
     | Am
     | 17
     | FryEggman
     | 19
     | AmThe
     | Fry
     | 22
     | 23
     | FryAmEggman
     | The
     | 26
     | Fry
     | Am
     | 29
     | FryTheEggman
     | 31
     | Am
     | Fry
     | 34
     | The
     | FryAmEggman
     | 37
     | 38
     | Fry
     | AmThe
     | 41
     | FryEggman
     | 43
     | Am
     | FryThe
     | 46
     | 47
     | FryAmEggman
     | 49
     | The
     | Fry
     | Am
     | 53
     | FryEggman
     | The
     | Am
     | Fry
     | 58
     | 59
     | FryAmTheEggman
     | 61
     | 62
     | Fry
     | Am
     | The
     | FryEggman
     | 67
     | Am
     | Fry
     | The
     | 71
     | FryAmEggman
     | 73
     | 74
     | FryThe
     | Am
     | 77
     | FryEggman
     | 79
     | AmThe
     | Fry
     | 82
     | 83
     | FryAmEggman
     | The
     | 86
     | Fry
     | Am
     | 89
     | FryTheEggman
     | 91
     | Am
     | Fry
     | 94
     | The
     | FryAmEggman
     | 97
     | 98
     | Fry
     | AmThe""")
res2: String = 6 3,Fry 4,Am 5,The 6,Eggman

4

Python 2、 366 340 331バイト

このプログラムは、stdinを介して入力を受け取ります。

新しいアプローチ:

行の終わりからの距離によって、1つの出現のみの単語の係数を計算します。例(最後のサンプルから):DeliciousTartApplePiePieは次のように計算されます:[95,19,5,1][0]Appleは:[95,19,5,1][1]です。

import sys
import re
d=[(i,re.findall('[A-Z][a-z]*',l)[::-1])for i,l in enumerate(sys.stdin)]
e=101-len(d)
print e," ".join(`x`+','+`y`[1:-1]for x,y in sorted({next((j-i for j,t in d if j>i and w in t),[x for x in range(i+e,0,-1)if(i+e)%x==0][d[i][1].index(w)]):w for w,i in{w:i for i,l in d[::-1]for w in l}.items()}.iteritems()))

古いアプローチ:

import sys
import re
l=[(i,re.findall('[A-Z][a-z]*',l))for i,l in enumerate(sys.stdin)]
e=101-len(l)
d={}
for i,s in l:
 for w in s[::-1]:
  if w not in d.values():
   d[next((j-i for j,t in l[i+1:]if w in t),next(m for m in range(i+e,0,-1)if(i+e)%m==0and m not in d))]=w 
print e," ".join(`x`+','+`y`[1:-1]for x,y in sorted(d.iteritems()))

使用法:

python FizzBuzzReverseSolver.py < Sample1.txt

説明(古いアプローチの):

  • 一般に、プログラムは、行番号と単語のリスト(例えばのリストを作成します[(0, []), (1, ['Ninja']), (2, ['Bear']), ...]
  • すべての行の各単語(行の終わりから開始):
    • 単語の次の出現を見つけて、違いと単語を事前定義された辞書に挿入します。
    • 見つからない場合は、辞書にまだ存在しない行番号(それ自体を含む)の最大要素と単語を辞書に挿入します。
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.