私のサフィックスはどのタイプですか?


10

はじめに

そのため、サフィックスソーティングアルゴリズムの研究、手作業およびコードによる新しいアイデアの評価に再び時間を費やしてきました。しかし、私はいつも自分のサフィックスのタイプを覚えるのに苦労しています!私のサフィックスのタイプを教えていただけますか?

左端何?

多くのサフィックスソートアルゴリズム(SAIS、KA、私自身のdaware)は、サフィックスをさまざまなタイプにグループ化してソートします。SタイプLタイプの2つの基本タイプがあります。Sタイプのサフィックスは、次のサフィックスよりも辞書順で小さい(S小さい)接尾辞であり、それが辞書順で大きい場合(Lアーガー)はLタイプです。左端のS型LMS型)だけのことである:A S型が付け加えているサフィックスL型接尾辞。

これらのLMSタイプのサフィックスの特別な点は、一度ソートすると、他のすべてのサフィックスを線形時間でソートできることです。すごくないですか?

チャレンジ

文字列が指定された場合、その文字列内の他のどの文字よりも小さい(たとえば、nullバイトよりも小さい)特殊文字で終了すると想定します。各サフィックスのタイプ対応する文字を出力します。

どのタイプにどのcharを使用するかは自由に選択できますが、すべて印刷可能である限り()は好きL, S and *です。L-, S- and LMS-type0x20 - 0x7E

文字列mmiissiissiippi出力がある場合(を使用する場合L, S and *):

 LL*SLL*SLL*SLLL

たとえば、1つ目Lは、mmiissiissiippi$辞書式にmiissiissiippi$$追加された最小文字を表す)よりも大きいという事実によるものです。

L - mmiissiissiippi$ > miissiissiippi$
L - miissiissiippi$  > iissiissiippi$
* - iissiissiippi$   < issiissiippi     and preceeded by L
S - issiissiippi$    < ssiissiippi$
L - ssiissiippi$     > siissiippi$
L - siissiippi$      > iissiippi$
* - iissiippi$       < issiippi$        and preceeded by L
S - issiippi$        < ssiippi$
L - ssiippi$         > siippi$
L - siippi$          > iippi$
* - iippi$           < ippi$            and preceeded by L
S - ippi$            < ppi$
L - ppi$             > pi$
L - pi$              > i$
L - i$               > $

さらにいくつかの例:

"hello world" -> "L*SSL*L*LLL"
"Hello World" -> "SSSSL*SSLLL"
"53Ab§%5qS"   -> "L*SSL*SLL"

ゴール

私はピーター・コーデスを困らせるためにここにいるわけではありません(いつかスタックオーバーフローでこれをやるつもりです)。私は非常に怠惰なので、これはもちろんです!バイト単位の最短の回答が優先されます。


編集:文字の順序は、バイト値によって指定されます。つまり、compareはCのようになりますstrcmp

Edit2:コメントで述べたように、出力は各入力文字に対して単一の文字でなければなりません。私はそれが「文字列を返す」と理解されると仮定しましたが、少なくとも1つの回答が単一の文字のリストを返すようです。既存の回答を無効にしないために、単一の文字(または出力時に1文字のみの結果となる整数)のリストを返すことができます。


線形時間のヒント:

  1. これは、2つの並列フォワード反復または単一のバックワード反復で実行できます。
  2. 各サフィックスの状態は、最初の2文字と2番目の文字のタイプにのみ依存します。
  3. 逆方向入力をスキャンするこのようなLまたはSを決定することができる:$t=$c<=>$d?:$t(PHP 7)、ここで、$c現在の文字が$d前と$t前タイプ。
  4. PHPの回答をご覧ください。明日、賞金を授与します。

これが私の最初の質問です:) Sandboxには2つの賛成票があり、コメントはありませんでしたので、投稿する準備ができていると思います。お気軽にご提案ください!
クリストフ

入力に表示できる文字は何ですか?
マーティンエンダー2017年

@MartinEnder文字列がサポートするすべての文字(c++スタイル文字列のnullバイトなど)。バイナリデータと考えてください。
クリストフ

どういう*意味ですか?
Leaky Nun 2017年

@LeakyNun *は、対応するサフィックスがタイプであることを意味しleft most s-typeます。A S-type suffix that is preceeded by a L-type suffix.
クリストフ

回答:


7

Haskell64 53 48 42バイト

(0!)
k!(x:y)|x:y>y=1:2!y|2>1=k:0!y
_![]=[]

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

Char代わりにInt

suffixes :: String -> String
suffixes = go 'S'
 where
   go :: Char -> String -> String
   go _ "" = ""
   go lorstar s | s > tail s = 'L' : go '*' (tail s)
                | otherwise  = lorstar : go 'S' (tail s)

匿名関数が許可されているため、z=削除できます。
Ørjanヨハンセン

Haskellが読めない。簡単な説明をお願いします。
クリストフ

1
@Christoph:このgo関数は2つの引数を取ります。1つ目は、S状況を説明するために使用する必要があるものを表す文字です。2番目は文字列です。それは再帰的にその文字列を通過し、各ステップで最初の文字を削除します(それが何をするかですtail)。トリックは、最初の引数に設定されることで*前の結果であった場合L、またはSそうでなければ。このように、an *またはan Sを使用する必要がある場合は、最初の引数を直接使用できます。それが理にかなっていると思います。
bartavelle 2017年

それはかなりいい考えです!私はもっ​​と賢いアイデアを見たいと思っています:)
クリストフ

@ØrjanJohansenTIOで結果を準備するにはどうすればよいですか?
bartavelle 2017年

6

ゼリー 25 23 21 20  19 バイト

Ṛ;\UỤỤIṠµI2n×ịØDṚ;0

以下を使用して、文字のリストを出力する完全なプログラム:

L: 0
S: 8
*: 9

(リンクとして、最後の項目(ゼロ)を除くすべての項目が文字であるリストを返します。)

オンラインでお試しください!または、テストスイートを参照してください(に変換してLS*)。

どうやって?

Ṛ;\UỤỤIṠµI2n×ịØDṚ;0 - Link: list of characters, s  e.g. "cast"
Ṛ                   - reverse                           "tsac"
  \                 - cumulative reduce by:
 ;                  -   concatenation                   ["t","ts","tsa","tsac"]
   U                - upend (reverse each)              ["t","st","ast","cast"] (suffixes)
    Ụ               - sort indexes by value             [3,4,2,1] (lexicographical order)
     Ụ              - sort indexes by value             [4,3,1,2] (order of that)
      I             - incremental differences           [-1,-2,1] (change)
       Ṡ            - sign                              [-1,-1,1] (comparisons)
        µ           - monadic chain separation, call that x
         I          - incremental differences           [0,2] (only (-1,1) produce 2s)
          2         - literal 2                         2
           n        - not equal?                        [1,0] (indexes of * will be 0)
            ×       - multiply by x (vectorises)        [-1,0,1] (make indexes of *s 0)
              ØD    - decimal yield                     "0123456789"
             ị      - index into (1-indexed & modular)  ['8','9','0']
                Ṛ   - reverse                           ['0','9','8']
                 ;0 - concatenate a zero                ['0','9','8',0]
                    - implicit print                     0980
                    -                              i.e. "L*SL"

簡単な説明を追加していただけませんか?
クリストフ

2
もちろんやります-私はまずゴルフの可能性について考えています...
ジョナサンアラン


@LeakyNunどうやってうまくやったの?あなたは私+が文字列でベクトル化しているように思えるバグを使用していますが、根本的な結果は実際にはジェリーの反復可能ではなく文字列(!)(たとえば、try +@/L€または+@/L€€or ...)
Jonathan Allan

@JonathanAllanはい、+実際の文字列を生成します。これは文書化されていない機能、またはいわゆるバグです。
Leaky Nun

3

Python 3、92 87 74 69 65バイト

s=input()
c=1
while s:d=s<s[1:];print(d+(c<d),end='');s=s[1:];c=d

用途0のためにL1のためにS、と2のために*。入力文字列を引用符で囲みます。これは慣例で許されていると思います。

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

使用例:

mmiissiissiippi
002100210021000

Leaky Nunのおかげで5バイト節約、ovsのおかげで4バイト節約




3

JavaScript(ES6)、51 45バイト

f=(c,d)=>c&&(d<(d=c<(c=c.slice(1))))+d+f(c,d)

@Neilのおかげで6バイトが節約されました。

演習の再帰的な解決策。

f=(c,d)=>c&&(d<(d=c<(c=c.slice(1))))+d+f(c,d)

console.log(f('mmiissiissiippi')); //LL*SLL*SLL*SLLL   002100210021000
console.log(f('hello world'));     //L*SSL*L*LLL       02110202000
console.log(f('Hello World'));     //SSSSL*SSLLL       11110211000
console.log(f('53Ab§%5qS'));       //L*SSL*SLL         021102100


6バイトを節約:f=(c,d)=>c&&(d<(d=c<(c=c.slice(1))))+d+f(c,d)
Neil

おかげで、@ニール、どこかに最適化が必要であることがわかっていました。
リックヒッチコック

2

JavaScript(ES6)、52バイト

f=
s=>s.replace(/./g,_=>(c<(c=s<(s=s.slice(1))))+c,c=1)
<input oninput=o.textContent=f(this.value)><pre id=o>

@ L3viathanの回答のポート。


1
@RickHitchcockおっと、どういうわけか私はなんとかして移植できc=1ましたc=0...
Neil


1

Haskell77 75バイト、線形時間

f(a:b:c)|let g"L"|a<b="SL";g"S"|a>b="L*";g d=d++d;d:e=f$b:c=g[d]++e
f _="L"

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

使い方

これは再帰を使用して、文字列の先頭から一度に1文字ずつ削除します。(Haskellの文字列型は単一にリンクされた文字のリストであるため、これらの各ステップは一定時間です。)

  • abが1文字でcが任意の(空の可能性がある)文字列である文字列abcの場合、
    • fabc)= SL eの場合、 FBC)= L Eと< B
    • fabc)= L * eただしただしfbc)= S eおよびa > bの場合
    • fabc)= LL eの場合、 FBC)= LとEと≥ B
    • fabc)= SS eただしf BC)= SとEと≤のB
  • 単一文字ストリングの場合、afa)=L。

1
説明をお願いします。
R. Kap

これが線形時間で実行されることを検証できるように、説明を入力してください。
クリストフ

@Christophが追加されました。
Anders Kaseorg 2017年

@AndersKaseorg追加ありがとう!悲しいことに、これは他のHaskellの回答に比べてかなり冗長に見えます。これを使用しないことでさらにゴルフをすることができS, L and *ますか?
クリストフ

1
@Christoph明確に言う[1,1,2,0,1,1,2,0,1,1,2,0,1,1,1]と、1桁の数字のリストであり、1文字のリストではありません。私の場合、数値のリストを出力してもバイトを節約できないと思います。
Anders Kaseorg 2017年

1

Python 265の 55バイト

基づいて再帰的なバージョン、L3viathanの答え使用して、012ようLS*

def g(s,d=2):c=s<s[1:];return s and`c+(d<c)`+g(s[1:],c)

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

Python 3 65の 59バイト

再帰的なソリューション使用してLS*

f=lambda s:s and('LS'[s<s[1:]]+f(s[1:])).replace('LS','L*')

文字列を前から実行し、すべてのインスタンスLSL*

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


1
blah if s else''s and blah6バイト節約します。Python 2では、str(blah)`blah`2番目のソリューションでさらに3バイトが節約されます。
Anders Kaseorg 2017年

1

PHP、82バイト、線形時間

for($a=$argn;a&$c=$a[$i-=1];$d=$c)$a[$i]=2+$t=$d<=>$c?:$t;echo strtr($a,[13=>12]);

入力を右から左にウォークし、各文字をタイプに置き換えます。

$t=$d<=>$c?:$t

現在および前の文字(-1または1)を指定して型を計算します。等しい場合、タイプは変更されません。


アイデアのための1strtr
イェルクHülsermann

1

PHP、70バイト

L = 1、S = 0、* = 2

代わりに§+3バイトの最後のテストケースにはマルチバイトサポートが必要ですmb_substrsubstr

for(;$s=&$argn;$s=$u)$r.=$l=($l&1)+(1&$l^($s>$u=substr($s,1)));echo$r;

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

PHP、71バイト

L = 1、S = 0、* = 2

for(;$s=&$argn;$s=$u)$r.=+($s>$u=substr($s,1));echo strtr($r,[10=>12]);

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

PHP、74バイト

for(;$s=&$argn;$s=$u)$r.=SL[$s>$u=substr($s,1)];echo strtr($r,[LS=>"L*"]);

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


$s=&$argnかなり賢い!私はもっ​​と良い答えがあると確信しています;)うまくいけば誰かがそれを思い付くでしょう:)
Christoph

@Christoph私は何かを逃しているような気がします。私は最後のLSはvaribaleで*保存しようとしていますが、それは長いです
イェルクHülsermann

@Christophはあなたがそういう意味ですか?最後のテストケースが偽である理由は本当にわかりませんでした
イェルクHülsermann

@Christophわかりました入力が単純​​なASCII範囲にない場合、mb_substr代わりに使用する必要がある最後のテストケースで機能しない理由をsubstr確認しました。最後のテストケースをサポートする必要はありますか?
イェルクHülsermann

1
@Christophはこの場合、ありがとうございました私はとの最後のテストケースを無視§
イェルクHülsermann
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.