ルックアンドセイシーケンス:ローマ数字版


20

チャレンジの説明

Look-and-sayシーケンスに関連するいくつかの課題がありました。クイックリマインダー:

  • シーケンスは、1で始まります
  • このシーケンスの後続の用語は、前の用語の繰り返し数字の各グループを列挙することにより生成されます。

したがって、最初のいくつかの用語は次のとおりです。

1        "one"
11       "one one" (we look at the previous term)
21       "two ones"
1211     "one two, one one"
111221   "one one, one two, two ones"
312211   "three ones, two twos, one one"

今度は同じことをしましょうが、代わりにローマ数字を使用します。最初からI同じルールに従います(代わりに数字カウントルールを文字に適用するためIVXone one, one five, one ten代わりに、one four, one tenまたは他の方法で読み取ります)。

I           "one"
II          "one one"
III         "two ones" = "II" + "I"
IIII        "three ones" = "III" + "I"
IVI         "four ones" = "IV" + "I"
IIIVII      "one one, one five, one one"
IIIIIVIII   "three ones, one five, two ones" = ("III" + "I") + ("I" + "V") + ("II" + "I")

次のNいずれかの正の整数を指定します。

  • Nこのシーケンスの最初の数字を出力します(妥当なセパレーターはもちろん、["I", "II", "III", ...]
  • Nこのシーケンスのth番目の用語を出力します(0インデックスが付いている場合があります)。

これは課題なので、をできるだけ短くすることを忘れないでください!

編集:私は常に整数をローマ数字として表現するための1つの標準/優先方法があると信じています(の代わりに95->のXCVようにVC)。私がオンラインで見つけたローマ数字のコンバーターのカップルは私の意見を裏付けています。疑問がある場合は、オンラインコンバーターを使用してください。すべての可能なエッジケースとローマ数字の記述の特定の規則をリストすることは、この課題のポイントではありません。

EDIT2:@PeterTaylorと@GregMartinは指摘数字だけ小さいか等しい5あなたはローマ数字のあいまいさを心配する必要はありませんので、順に表示されます(数字1- 8ですIIIIIIIVVVIVII、及びVIII


各整数に一意のローマ数字表現はありません。どの数字を表現する必要があり、それらの数字のどの表現が有効ですか?
ピーターテイラー

「各整数に一意のローマ数字表現がない」とはどういう意味ですか?好き4/ IV/ IIII?または95/ XCV/ VC?整数を表現するユニークな方法が常にあるとは限りませんが、常に優先される(標準の)方法があると確信しています。間違っている場合は修正してください。
shooqie

1
ローマ数字でどこまで行かなければなりませんか?
マルティセン

はい、両方の場合。後者の場合、望ましいのは意見の問題だと思います。
ピーターテイラー

9
@shooqieこれらの詳細が明らかにされなかった場合、回答をどのように比較しますか?解釈するために残された特定のエッジケースがある場合、実際のスコアはあなたが思いつくかもしれないゴルフのトリックよりも大きな違いを生む可能性があるため、無意味になります。
マーティンエンダー

回答:


17

Perl、49バイト

+1を含む -p

STDINの0ベースのインデックスで実行します。たとえば

ecce.pl <<< 14

ecce.pl

#!/usr/bin/perl -p
s,(.)\1*,$&/$1%182 .$1,eg for($_=/$/)x$`;y;19;IV

魔法の式はとても魔法です。

通常($_=//)x$'、ループ制御を1バイト短くするために使用しますが、このサイトでスコアを付けるとハンディキャップが2になるため、1バイト長くなります。古いperlでは、前にスペースを削除できますfor。perlの一部のバージョンでは;、音訳を終了するために最終を追加する必要があります。しかし、上記で与えられているのは私のシステムで動作するコードです。

説明

ソリューションからコードへの逆方向の作業:

必要な文字列変換:

I     -> II
II    -> III
III   -> IIII
IIII  -> IVI
IIIII -> VI

V     -> IV
VV    -> IIV

各置換は、繰り返される文字で終了します。正規表現を使用して同じ文字のシーケンスを取得する/(.)\1*/ので、これを追加することで実行できます$1。の前の部分->はにあり$&ます。それで私はまだ必要です:

I     -> I
II    -> II
III   -> III
IIII  -> IV
IIIII -> V

V     -> I
VV    -> II

Ias 1およびVasとして書く:

1     -> 1
11    -> 11
111   -> 111
1111  -> 19
11111 -> 9

9     -> 1
99    -> 11

前の部分を->繰り返し数字で除算すると、次のようになります。

1     -> 1
11    -> 11
111   -> 111
1111  -> 19
11111 -> 9

1     -> 1
11    -> 11

そのため、元の繰り返しVはもう例外ではありません。だから私はこれを実現する式が欲しい:

1     -> 1
11    -> 11
111   -> 111
1111  -> 19
11111 -> 9

そして、これは簡単なモジュロ182で行うことができます:

1     % 182 = 1
11    % 182 = 11
111   % 182 = 111
1111  % 182 = 19
11111 % 182 = 9

(これはさえ取得IIIIIIVIはここでは必要ありません正しくなります)

左があるすべてのことに取り組んで変数を初期化している1インデックス0のために、ループ内でこの変換を繰り返し、最後に置き換える1ことにより、Iおよび9によってV

19および182この単純な式が機能する唯一のパラメータの組み合わせです。


2
これは天才です!:)
リン

10

Mathematica、113 90 83バイト

長さを25%以上短縮する提案をしてくれたMartin Enderに感謝します!

Mathematicaで高レベルのコマンドを披露します。

Nest[Flatten[Characters@{RomanNumeral@#,#2}&@@@Reverse@@@Tally/@Split@#]&,{"I"},#]&

引数Nを取り、この(0から始まる)シーケンスのN番目の要素を文字のリストとして出力する純粋な関数。少し広げる:

Nest[
  Flatten[
    Characters @ {RomanNumeral@#,#2}& @@@
      Reverse @@@ Tally /@ Split@ #
    ]& ,
  {"I"}, #]&

外側Nest{"I"}、N から始まる中央の4行関数を繰り返します。行4は、入力ローマ数字の文字リストを類似した文字の実行に分割し、各実行をTallyでカウントし、カウントしている文字の前にカウントを置きます。行3は、カウントをローマ数字としてレンダリングし、それらのローマ数字を文字のリストに分割します。のFlattenコマンドは、リスト全体を1次元のリストに縮小します。

初期バージョンは次のとおりです。

Nest[
  "" <> Flatten[{RomanNumeral@#[[1]], #[[2]]} & /@
    (Reverse@#[[1]] & /@ 
      Tally /@
        Split@Characters@#)] &,
  "I", #] &

3
Grrr Mathematica;)
ベータ崩壊

@@@代わりに/@使用する場合#、andの#2代わりに#[[1]]andを使用できます#[[2]]。また、文字のリストは許容可能な文字列タイプであるため、それらを使用して、の使用を避けることができますCharacters@
マーティンエンダー

@MartinEnderああ、@@@似たようなショートカットがあったに違いない!許容可能な文字列タイプである文字のリストについて(コードを短縮することに同意します):このサイトに投稿して、コミュニティ標準を説明するものを教えていただけますか?
グレッグマーティン


1
さらにいくつかの貯蓄:Charactersスレッドを自動的に使用できるようには@Reverse@#&当然のことながら、プレーンと同じであるReverseあなたはまた、それらの括弧を必要としない場合には、。またFlatten、括弧を追加して機能させる必要がある場合、プレフィックス表記(の場合)は何も保存しません。これらすべてを組み合わせる:Nest[Flatten[Characters@{RomanNumeral@#,#2}&@@@Reverse@@@Tally/@Split@#]&,{"I"},#]&
マーティンエンダー

8

CJam(33 30バイト)

"I"{e`{(4md1$^'I*\'V*@}%e_}ri*

オンラインデモ

実装の正確さの鍵は、次の定理です。

第一世代がの場合、Iランレングスは5より大きくなりません

補題:第一世代がの場合、I文字列はを含みませんVVV。証明は矛盾によるものです。最初のインデックスが存在することを仮定しnているためn番目の世代が含まれていますVVV。それがVVV壊れる場合(a)V VV、前の世代からの変換は悪いです(a+5)V。だから、それはあるに違いありませんVV V(d)、そして前の世代が含まれていてVVVVV、の選択に矛盾していnます。

ここmで、mth世代にが含まれる最初のインデックスがあると仮定します...IIIIII...。文字列にIと以外の数字は使用できないことに注意してくださいV。これは、前の世代では9 I秒または9 V秒の実行が行われていないためです。Isの最大4つは、I前の文字列のsの実行に由来するため、前の文字列の対応するセクションは...IIIVV...を与える必要があります... IIII IIV ...。以来VV世代では、m-1から来ていませんVVVVV(補題を参照)、第二は、V桁のランレングスでなければならないIので、世代で、m-1私たちは持っています...IIIVVI...。我々は初期たいのでISを与えるIIIIといませんIVIか、VI、文字列の先頭またはV

私たちが(...V)?IIIVVI...世代m-1で持っている場合、私たちは世代で何を持っていm-2ますか?私たちはすでにVVgenのことを観察しました。m-1として解析する必要があります(a)V V(I)

私たちが取ると仮定しますa=2(...V)?I IIV VI...実際にはそうでなければなりませんが...VI IIV VI...、その先頭Vはの一部かもしれませんIV。そのため、前の世代では、(...V)? IIII VV IIIII...またはのいずれかを使用しています(...V)? IIIII VV IIIII。いずれにせよ、問題が発生しVVIIIIIます。2番目Vはランレングスでなければなりませんが...VI IIII...、同じディジットの次の(ランレングス、ディジット)ペアが必要です。

だから、でなければなりませんa=1(...V)?II IV VI...。生成mは6 I秒実行の最初である(...V)? II IV VI...ため、でなければならないため、生成m-2はになり(...V)? I V IIIII...ます。...VIVIIIII...不可能です。しかしV、同じ数字を持つ2つの連続した(ランレングス、数字)ペアで終わる2番目の数字を解釈することを選択します。

したがって、生成m-2はまたは^IVIIIII...として解析する必要があります。これらはそれぞれまたはとして生成を行います。^IV IIII I(V)...^IV III II(V)...m-3^V III V ...^V II VV...

しかし、で始まる最初の文字列で始まる文字列の先頭を見るとV、サイクルが得られます:

    VI IV I...
    IV III IV ...
    II IV IVI ...
    IIII IV II IV ...

ですから、VIIIVまたはで始まる世代はありませんVIIVV。私たちはそのようなものがないと結論しなければなりませんm

解剖

"I"          e# Initial generation
{            e# Loop...
  e`         e#   Run-length encode
  {          e#   Foreach [run-length char] pair...
    (        e#     Extract the run-length r
    4md1$^   e#     Get the number of Vs and the number of Is
             e#     The number of Vs is r/4 ; the number of Is is (r%4)^(r/4)
    'I*\'V*@ e#     Repeat strings the appropriate number of times and reorder
  }%
  e_         e#  Flatten to a simple string
}ri*         e# ... n times, where n is taken from stdin

6

Python 3、195バイト

ローマ数字に無駄なバイトがたくさんあるので、そこでゴルフをする必要があるでしょう。

@ El'endiaStarman、@ Sherlock9、@ Shooqieに感謝

import re
def f(x,r=""):
 for v,i in(5,"V"),(4,"IV"),(1,"I"):a,x=divmod(x,v);r+=i*a
 return r
s="I"
for i in[0]*int(input()):print(s);s=re.sub(r'(.)\1*',lambda m:f(len(m.group()))+m.group()[0],s)

できた!


角括弧は省略できますfor v,i in(5,"V"),(4,"IV"),(1,"I")
。– shooqie

D:私はあなたがそれを行うことができるとは考えなかった@shooqie
ベータ崩壊

for v,i in(5,"V"),(4,"IV"),(1,"I"):a,x=divmod(x,v);r+=i*aバイトを保存します。
シャーロック9

@βετѧΛєҫαγ:また、i(のようにfor i in range(...))使用していないようです。私は手を出そうとしましたexecが、これは1「sub」メソッドでエスケープされているため、コードが混乱しているようです。回避策を見つけることができませんでした。
shooqie

@shooqie私はそれを取り除くことで少し短くしたrange
ベータ崩壊

4

R、110の 107バイト

as.romanと組み合わせるとrle、これが簡単になります。スコープの乱用と組み込みの猫の動作は<<-、数バイトを節約します。

x="I"
replicate(scan(),{r=rle(strsplit(x,"")[[1]])
x<<-paste(rbind(paste(as.roman(r$l)),r$v),collapse="")})

コンソールからNを取り込みます。シーケンスの最初の2からN項を出力します(これは仕様の範囲内であると思います...)

 [1] "II"                                                                                                                                                                                                                                     
 [2] "III"                                                                                                                                                                                                                                    
 [3] "IIII"                                                                                                                                                                                                                                   
 [4] "IVI"                                                                                                                                                                                                                                    
 [5] "IIIVII"                                                                                                                                                                                                                                 
 [6] "IIIIIVIII"                                                                                                                                                                                                                              
 [7] "VIIVIIII"                                                                                                                                                                                                                               
 [8] "IVIIIIVIVI"                                                                                                                                                                                                                             
 [9] "IIIVIVIIVIIIVII"                                                                                                                                                                                                                        
[10] "IIIIIVIIIVIIIIVIIIIIVIII"                                                                                                                                                                                                               
[11] "VIIVIIIIIVIVIIVVIIVIIII"                                                                                                                                                                                                                
[12] "IVIIIIVVIIVIIIVIIIIIVIIIIVIVI"                                                                                                                                                                                                          
[13] "IIIVIVIIIVIIIIVIIIIIVVIIVIVIIVIIIVII"                                                                                                                                                                                                   
[14] "IIIIIVIIIVIIIIIVIVIIVVIIIVIIIIVIIIVIIIIVIIIIIVIII"                                                                                                                                                                                      
[15] "VIIVIIIIIVVIIVIIIVIIIIIVIIIIIVIVIIVIIIIIVIVIIVVIIVIIII"                                                                                                                                                                                 
[16] "IVIIIIVVIIIVIIIIVIIIIIVVIIVVIIVIIIVIIIIVVIIVIIIVIIIIIVIIIIVIVI"                                                                                                                                                                         
[17] "IIIVIVIIIVIIIIIVIVIIVVIIIVIIIIIVIIIIVIIIIIVIVIIIVIIIIVIIIIIVVIIVIVIIVIIIVII"                                                                                                                                                            
[18] "IIIIIVIIIVIIIIIVVIIVIIIVIIIIIVIIIIIVVIIVIVIIVVIIVIIIVIIIIIVIVIIVVIIIVIIIIVIIIVIIIIVIIIIIVIII"                                                                                                                                           
[19] "VIIVIIIIIVVIIIVIIIIVIIIIIVVIIVVIIIVIIIIVIIIVIIIIIVIIIIVIIIIIVVIIVIIIVIIIIIVIIIIIVIVIIVIIIIIVIVIIVVIIVIIII"                                                                                                                              
[20] "IVIIIIVVIIIVIIIIIVIVIIVVIIIVIIIIIVIIIIIVIVIIVIIIIIVVIIVIVIIVVIIIVIIIIVIIIIIVVIIVVIIVIIIVIIIIVVIIVIIIVIIIIIVIIIIVIVI"                                                                                                                    
[21] "IIIVIVIIIVIIIIIVVIIVIIIVIIIIIVIIIIIVVIIVVIIVIIIVIIIIVVIIIVIIIIVIIIVIIIIIVIIIIIVIVIIVVIIIVIIIIIVIIIIVIIIIIVIVIIIVIIIIVIIIIIVVIIVIVIIVIIIVII"                                                                                             
[22] "IIIIIVIIIVIIIIIVVIIIVIIIIVIIIIIVVIIVVIIIVIIIIIVIIIIVIIIIIVIVIIIVIIIIIVIVIIVIIIIIVVIIVVIIVIIIVIIIIIVIIIIIVVIIVIVIIVVIIVIIIVIIIIIVIVIIVVIIIVIIIIVIIIVIIIIVIIIIIVIII"                                                                      
[23] "VIIVIIIIIVVIIIVIIIIIVIVIIVVIIIVIIIIIVIIIIIVVIIVIVIIVVIIVIIIVIIIIIVVIIVIIIVIIIIVVIIIVIIIIIVIIIIVIIIIIVVIIVVIIIVIIIIVIIIVIIIIIVIIIIVIIIIIVVIIVIIIVIIIIIVIIIIIVIVIIVIIIIIVIVIIVVIIVIIII"                                                   
[24] "IVIIIIVVIIIVIIIIIVVIIVIIIVIIIIIVIIIIIVVIIVVIIIVIIIIVIIIVIIIIIVIIIIVIIIIIVVIIIVIIIIVIIIIIVIVIIIVIIIIIVVIIVIVIIVVIIIVIIIIIVIIIIIVIVIIVIIIIIVVIIVIVIIVVIIIVIIIIVIIIIIVVIIVVIIVIIIVIIIIVVIIVIIIVIIIIIVIIIIVIVI"                             
[25] "IIIVIVIIIVIIIIIVVIIIVIIIIVIIIIIVVIIVVIIIVIIIIIVIIIIIVIVIIVIIIIIVVIIVIVIIVVIIIVIIIIIVIVIIVVIIVIIIVIIIIIVVIIIVIIIIVIIIVIIIIIVIIIIIVVIIVVIIVIIIVIIIIVVIIIVIIIIVIIIVIIIIIVIIIIIVIVIIVVIIIVIIIIIVIIIIVIIIIIVIVIIIVIIIIVIIIIIVVIIVIVIIVIIIVII"

1

JavaScript(ES6)、107

N番目の項0を返す再帰関数

f=(n,r='I')=>n?f(n-1,r.match(/I+|V+/g).map(x=>((n=x.length)-4?'VIII'.slice(n<5,1+n%5):'IV')+x[0]).join``):r

テスト

f=(n,r='I')=>n?f(n-1,r.match(/I+|V+/g).map(x=>((n=x.length)-4?'VIII'.slice(n<5,1+n%5):'IV')+x[0]).join``):r

function update() {
  O.textContent=f(I.value)
}

update()
<input id=I value=25 type=number oninput='update()'><pre id=O></pre>


1

Perl 6、62バイト

{("I",{S:g/(.)$0*/{<I II III IV V>[$/.chars-1]~$0}/}...*)[$_]}

ゼロベースのインデックスを受け入れる匿名関数。

発生する可能性のある繰り返し数字のグループは次のとおりであるため、5より大きいローマ数字は必要ないという事実を利用します。

I     -> II
II    -> III
III   -> IIII
IIII  -> IVI
IIIII -> VI

V     -> IV
VV    -> IIV

オンラインで試してみてください

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