末尾の真実を数える


59

私の親愛なる友人や同僚にインスパイアされ、その記念に、

ダン・バロネット

ダンバロネット、1956 –2016。RIP

彼はこのタスクに対する最短のAPLソリューションを見つけまし

仕事

ブールリストを指定して、後続の真理値の数をカウントします。

事例の例

{}0

{0}0

{1}1

{0, 1, 1, 0, 0}0

{1, 1, 1, 0, 1}1

{1, 1, 0, 1, 1}2

{0, 0, 1, 1, 1}3

{1, 1, 1, 1, 1, 1}6


リストをゼロと1の文字列として取得できますか?例えば01100
アドナン

@Adnanは、ご使用の言語でブールリストを表現する最も一般的な方法である場合にのみ使用します。
アダム

71
あなたの損失でごめんなさい。
マーティンエンダー

6
@MartinEnderありがとう 今後は大変です。ダンは、私がダイアログで働くために知っておくべきすべてを教えてくれました。
アダム

5
ダンに別れを告げる。RIP ...
エリックOutgolfer

回答:


36

Dyalog APL、6 2バイト

⊥⍨

TryAPLでテストします

使い方

(uptack、dyadic:decode)はベース変換を実行します。左のオペランドがベクトルの場合、混合ベース変換を実行ます。これは、このタスクに最適です。

基底ベクトルをB = BのN、⋯、B 0及び桁ベクトルA = N、⋯、0B⊥Aは変換混合基にB、すなわち、それは計算B 0 ⋯B N-1 n +⋯+ b 0 b 1 a 2 + b 0 a 1 + a 0

ここで、(チルダ分音記号、通勤)は次のように演算子を左に変更します。モナドコンテキストでは、等しい左および右引数で演算子を呼び出します。

例えば、⊥⍨として定義される計算した、0N +⋯+ 0 1 2 + 0 1 + 0、右から左へのすべての累積積の和。

以下のためにK末尾もの、K右端製品は1と他のすべては0それらの合計が等しくなるように、kは


14
ヒント:ダンはたった2バイトでそれをしました。
アダム

3
混合ベース変換!それは賢いです。
デニス

1
ああ。混合ベース変換、それが再び
コナーオブライエン

ブラボー!実際には、ダンのために、我々は特殊ケースに入れb⊥b⊥⍨b無限のスピードアップをあきらめ。
アダム

19

JavaScript(ES6)、21バイト

f=l=>l.pop()?f(l)+1:0

テストケース


これはどのように作動しますか?どのようにf(l)+1値を返します> 2か?
オリバー

@Oliverこれは再帰的なプロセスであり、と評価されl.pop()?(l.pop()?(l.pop()?(...etc...)+1:0)+1:0)+1:0ます。
アーナルド

そうですか。説明ありがとう。
オリバー

11

ゼリー、4バイト

ŒrṪP

オンラインでお試しください!またはすべてのテストケースを検証します。

リストが空の場合、奇妙な観察がいくつかあります。最初に、空のリストをランレングスエンコードすると、[]別の空のリストが返されます[]。次に、末尾を使用して最後の要素を取得すると、ランレングスエンコードされた配列の通常の要素であるペアの代わりにtail が返されます。その後、製品は、呼び出されたときに期待される結果を返します。0[value, count]P00

説明

ŒrṪP  Main link. Input: list M
Œr    Run-length encode
  Ṫ   Tail, get the last value
   P  Product, multiply the values together

または、ŒgṪS機能します!
リン

入力として空のリストに適切な出力を提供しますが、私は解剖を見て驚いています。その特別なケースを見てみませんか?
ピーターテイラー

@PeterTaylor私もそれが働いたことに驚いています。また、最初のリンクのコードが間違っていることに気付きました。
マイル

Jellyの@PeterTaylor は次のように実装されていますlambda z: iterable(z).pop() if iterable(z) else 0iterableリストで呼び出されると、リストを返すだけで、空のリストはもちろん偽物です。
FryAmTheEggman



10

Haskell、26 25バイト

a%b|b=1+a|0<3=0
foldl(%)0

使用法:

Prelude> foldl(%)0 [True,False,True,True]
2

ポイントフリーバージョン(26バイト):

length.fst.span id.reverse

boolリストの代わりに整数リストを使用(21バイト、Christian Sieversに感謝):

a%b=b*(a+1)
foldl(%)0

使用法:

Prelude> foldl(%)0 [1,0,1,1]
2

ポイントフリーバージョン(25バイト)

sum.fst.span(==1).reverse

整数リストの場合、foldlアイデアは次のように機能します。a%b=b*(a+1)
Christian Sievers

9

網膜7 5バイト

r`1\G

オンラインでお試しください!(最初の行は、改行で区切られたテストスイートを有効にします。)

Retinaの入力形式の定義は、完全に明確ではありません。Retinaには文字列以外の型の概念がないため(また、真実と偽りの通常の定義に使用できる値もありません)、私は通常、0および1(または一般的に肯定的なもの)を使用して、真実と偽りに対応しますそれぞれゼロまたはいくつかの一致。

単一文字表現では、リストの区切り文字も必要ありません(ある意味、文字列のみを含む言語のリスト表現のほうが自然です)。Adámは、これが受け入れ可能な入力形式であること確認しました。

正規表現自体に関しては、rightから左に\G一致し、各一致を前の一致にアンカーします。したがって、これは1文字列の末尾から何個のsを照合できるかをカウントします。


「はい、Retinaの場合、文字列のみを処理するため、「01」または「FT」の文字列が
適切

9

05AB1E12 10 6 5バイト

carusocomputingのおかげで1バイト節約されました

Î0¡¤g

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

説明

Î      # push 0 and input
 0¡    # split on 0
   ¤   # take last item in list
    g  # get length

0¡¤g4バイトです。
魔法のタコUr

@carusocomputing:いいね!これを書いたときに文字列の入力が問題ないかどうかはまだ明確ではありませんでしたが、今ではそうなっていることが
わかりました

J0¡¤gまだ短いです;)。
魔法のタコUr

@carusocomputing:残念ながらÎ、空の入力を処理する必要がありますが、それでも1バイト保存されています。ありがとう
ござい






5

C90(gcc)、46バイト

r;main(c,v)int**v;{while(0<--c&*v[c])r++;c=r;}

入力はコマンドライン引数(引数ごとに1つの整数)を介して行われ、出力は終了コードを介して行われます

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

使い方

rはグローバル変数です。その型はデフォルトでintになり、グローバルであるため、値はデフォルトで0になります。

関数の引数cのデフォルトもintです。n個のブール値の配列に対して整数n + 1を保持します。mainの最初の引数は、常に実行可能ファイルのパスです。

関数の引数vはとして宣言されint**ます。vの実際のタイプはになりますがchar**、各引数の最下位ビットのみを調べて文字0(コードポイント48)と1(コードポイント49)を区別するため、リトルエンディアンでは問題になりません。マシン。

whileループはcをデクリメントし、0と比較します。いったんcが到達した0を、我々はループから抜け出すだろう。これは、配列に0が含まれていない場合にのみ必要です。

10<--cが返される限り、c 番目のコマンドライン引数()を取得し、ポインターの逆参照()によって最初の文字を抽出します。私たちは、ビット単位のANDブールの取り状態が返されますので、文字(とそれに続く3ゴミバイト)のコードポイントを0に一度0が検出されたループを抜け出し、。v[c]*0<--c

コマンドライン引数であるが、残りの場合には、1r++インクリメントRをすることによって1こうして後続の数をカウント、1「Sを。

最後に、rc=rの計算値をcに保存します。デフォルト設定では、コンパイラは割り当てを最適化して削除します。実際に命令を生成します。以来、EAXレジスタの戻り値は、このことは、所望の出力を生成します。movl %eax, -4(%rbp)ret

このコードはC99では機能しないことに注意してください。C99は、メインの最後に到達するとメインから0を返します。


Isn't argc少なくとも1(とargv[0]ファイル名を含みますか)?の--c&&代わりに1バイトを保存できます0<--c&。gccの終了コードはから取得されargcますか?きちんとした。
タイタス

@タイタスそれは動作しません。*v[c]1または0のコードポイントなので、49または48であり、常に真実です。
デニス

C89およびC90では、gccはその時点でRAXにあるものをすべて返します。C99 は、最後に到達すると、メインから常に0を返します。
デニス

4

k、6バイト

+/&\|:

この関数構成は、言語の読みやすい兄弟であるsum mins reversein qに変換されます。minsはローリングミニマムです。


:をドロップできますか?
ストリートスター

4

J、9 3バイト

#.~

これは、再帰的な混合ベース変換です。これは、混合ベース変換と同じであるためです。 再び。

テストケース

   v =: #.~
   ]t =: '';0;1;0 1 1 0 0;1 1 1 0 1;1 1 0 1 1;0 0 1 1 1;1 1 1 1 1 1
++-+-+---------+---------+---------+---------+-----------+
||0|1|0 1 1 0 0|1 1 1 0 1|1 1 0 1 1|0 0 1 1 1|1 1 1 1 1 1|
++-+-+---------+---------+---------+---------+-----------+
   v&.> t
+-+-+-+-+-+-+-+-+
|0|0|1|0|1|2|3|6|
+-+-+-+-+-+-+-+-+
   (,. v&.>) t
+-----------+-+
|           |0|
+-----------+-+
|0          |0|
+-----------+-+
|1          |1|
+-----------+-+
|0 1 1 0 0  |0|
+-----------+-+
|1 1 1 0 1  |1|
+-----------+-+
|1 1 0 1 1  |2|
+-----------+-+
|0 0 1 1 1  |3|
+-----------+-+
|1 1 1 1 1 1|6|
+-----------+-+

2
ヒント:これは、ダンのソリューションのJ変換を使用して、わずか3バイトで実行できます。
アダム

1
@Adám私は解決策を探してみました。ベース変換を考えていませんでした。それは本当に彼の非常に賢いです!
コナーオブライエン

1
はい。それがダンだった。:-(
アダム

4

R、40 39 25バイト

@Dasonのおかげで完全に作り直されたソリューション

sum(cumprod(rev(scan())))

stdinから入力を読み取り、ベクトルを逆にして、の最初の要素が!=0ランレングスエンコーディングの最初の長さ(rle)を出力する場合はelseを返します0


1
2行目をに変更すると、バイトを保存できますifelse(r$v,r$l,0)[1]。(次の場合はベクトル化され、最初の要素を取得します。)
rturnbull

1
iflelseは必要ありません-r $ vとr $ lを掛けるだけです。
デイソン

しかし、合計(cumprod(REV())。)ルートはとにかくバイトの多くを保存してください
Dason

3

Haskell、24バイト

foldl(\a b->sum[a+1|b])0

リストを反復処理し、要素ごとに1つずつ追加し0、にヒットした後ににリセットしFalseます。

0/1入力の16バイト

foldl((*).(+1))0

リストが空でないことが保証されている場合、14バイトを取得できます。

sum.scanr1(*)1

これは、後ろから累積積を計算し、それらを合計します。累積積は、0がヒットするまで1のままで、その後0になります。したがって、1は後​​続の1に対応します。



3

C#6、103 72バイト

using System.Linq;
int a(bool[] l)=>l.Reverse().TakeWhile(x=>x).Count();

非ジェネリックリストを使用すると、ジェネリックリストが1バイト笑います

スコットのおかげで-31バイト


の配列を使用する場合はint、次の方法で逃げることができますint a(int[] l)=>l.Reverse().TakeWhile(i=>i>0).Sum();
Scott

@Scottもちろん、私は何を考えていたのですか...しかし、私はboolに固執します。質問は、ブール・リストを指定すると、それはC.ではありません
リンクン

Func<bool[], int>57バイト、つまりusing System.Linq;l=>l.Reverse().TakeWhile(x=>x).Count();
TheLethalCoder

2

Python、37バイト

f=lambda l:len(l)and-~f(l[:-1])*l[-1]

2

DASH、16バイト

@len mstr"1+$"#0

最短のDASHソリューションではありませんが、最短のDASHソリューションが私を悩ませています。その代わりに、この斬新なアプローチを投稿しています。

使用法:

(@len mstr"1+$"#0)"100111"

説明

@(                 #. Lambda
  len (            #. Get the length of the array after...
    mstr "1+$" #0  #. ... matching the argument with regex /1+$/
  )                #. * mstr returns an empty array for no matches
)

2

Scala、25バイト

l=>l.reverse:+0 indexOf 0

ゴルフをしていない:

l=>(l.reverse :+ 0).indexOf(0)

リストを逆にし、0を追加して、最初の0の前の要素数である0の最初のインデックスを見つけます


2

バッチ、57バイト

@set n=0
@for %%n in (%*)do @set/an=n*%%n+%%n
@echo %n%

入力をコマンドラインパラメーターとして受け取ります。加算する前に現在の値でアキュムレータを乗算することにより機能し、コマンドラインのゼロがカウントをリセットします。%%nnor %n%変数と同じではないことに注意してください。



2

Java 7、62バイト

int c(boolean[]a){int r=0;for(boolean b:a)r=b?r+1:0;return r;}

未ゴルフ&テストコード:

ここで試してみてください。

class M{
  static int c(boolean[] a){
    int r = 0;
    for (boolean b : a){
      r = b ? r+1 : 0;
    }
    return r;
  }

  public static void main(String[] a){
    System.out.print(c(new boolean[]{}) + ", ");
    System.out.print(c(new boolean[]{ false }) + ", ");
    System.out.print(c(new boolean[]{ true }) + ", ");
    System.out.print(c(new boolean[]{ false, true, true, false, false }) + ", ");
    System.out.print(c(new boolean[]{ true, true, true, false, true }) + ", ");
    System.out.print(c(new boolean[]{ true, true, false, true, true }) + ", ");
    System.out.print(c(new boolean[]{ false, false, true, true, true }) + ", ");
    System.out.print(c(new boolean[]{ true, true, true, true, true, true }));
  }
}

出力:

0, 0, 1, 0, 1, 2, 3, 6

2

Perl 5.10、22バイト

21バイト+ -aフラグ用の1バイト。正規表現ベースの式が行われたため...:p

配列の入力値はスペースで区切る必要があります。

$n++while pop@F;say$n

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


1
コマンドライン経由で引数を取る場合は少し短くなりますperl -E '$_++while pop;say' 0 1 1 0 1 1 1が、これは何も出力しません0(ただし、それが問題なのかどうかはわかりません!)
Dom Hastings

2

Perl、22バイト

21バイトのコード+ -pフラグ用の1バイト。

s/.(?=.*0)//g;$_=y;1;

実行するには:

perl -pE 's/.(?=.*0)//g;$_=y;1;' <<< "0 1 1 0 1 1 1"

(実際には、入力のフォーマットは、多くの問題ではありません:01101110 1 1 0 1 1 1[0,1,1,0,1,1,1]などすべての作業でしょう)


18バイトのバージョンから@Domヘイスティングスそれは許可されていない0と1の文字列として入力を供給する必要があります。

perl -pE '/1*$/;$_=length$&' <<< '0110111'

その愛情の;トリック:)フォーマットは、一つの連続した文字列がある場合を:perl -pE '/1*$/;$_=length$&' <<< '0110111'18のための、それは...しかし、ルールを曲げだかどうかわからない
ドムヘイスティングス

@DomHastingsええ、私も!(それを見せてくれてありがとう!)質問の最初と2番目のコメントは、ソリューションに必要な入力の形式を許可しません...しかし、入力の形式がもっとあれば、投稿を編集してバージョンを提案します自由。
ダダ

2

PHP、50バイト

<?=strlen(preg_filter('/.*[^1]/','',join($argv)));

奇妙なことに、正規表現を使用した最初の試行は、配列を
使用した試行よりも短くなりました...次のように使用します。

php tt.php 1 1 0 1 1

2

Ruby 37 32バイト

->n{n.size-1-(n.rindex(!0)||-1)}

false値の右端のインスタンスを見つける匿名関数を作成し、その値から始まるサブ配列のサイズをカウントします。

!00はRubyの真の値であるため、falseとして使用します。rindex配列内の値の最後のインデックスを見つけます。

使用法

boolean_list = [true, false, false, true]
->n{n.size-1-(n.rindex(!0)||-1)}[boolean_list]

1を返します


コマンドラインパラメータとして0と1の文字列を渡すことが許可された場合(ルビーがブール値のリストを表す方法ではありません)、24まで下げることができます:

$*[0]=~/(1*)\z/;p$1.size

これは、正規表現を使用し、正規表現によって返される文字列の長さを出力します。/(1*)\z/ここ\zで、文字列の末尾です。$*[0]渡される最初の引数であり、0と1の文字列です。

使用法:

trailing_truths.rb 011101

1を返します。


1
最後のfalse値のインデックスを取得したら、なぜ配列から要素を再度取得する必要があるのですか?
リーW

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