番号連鎖述語


27

問題:

あなたの仕事は、一連の数字の中で、すべての数字にその数字の前の数字の少なくとも1つが含まれているかどうかを判断することです。

たとえば、次の例は真実を返します。

[1, 12, 203, 0, 30]
             ^   ^ Contains a 0
        ^ Contains a 2
    ^ Contains a 1

以下はfalseyを返すはずです:

[1, 32, 23, 34]
    ^ Doesn't contain a 1, therefore false

あなたの提出物は、機能または完全なプログラムにすることができます。

入力:

入力には、合理的なタイプのシーケンスを使用できます。数字の配列、文字列の配列、数字の区切り文字列など。

ただし、順序は重要であるため、入力として受け入れることを選択する構造は、明らかに明確な順序を持たなければなりません。

入力は、stdinを介して、または引数として取得できます。

あなたは仮定することができます:

  • すべての数値は負でない整数になります

  • 入力には常に少なくとも2つの数字が含まれます

  • 入力番号は0で始まりません

出力:

出力は、上記の仕様が満たされているかどうかを表す、真実の値または偽の値(言語で定義)になります。

真/偽の値は、テスト間で一貫している必要はありません。

stdoutに出力するか、返すことができます。

テストケース:

True cases:
[1, 1, 1, 11, 111, 11, 1]
[12, 23, 34, 45, 56]
[65, 54, 43, 32, 21]
[123, 29, 9, 59, 55, 52, 2017, 2]
[1234567890, 19, 95, 5012, 23]

False cases:
[1, 2, 3, 4, 5, 1, 11] (2 doesn't contain a 1)
[12, 23, 33, 45] (45 doesn't contain a 3)
[98, 87, 76, 11, 12, 23] (11 doesn't contain a 7 or 6)

これはコードゴルフなので、バイト数が最小になります。

回答:


7

ゼリー5 4バイト

f2\Ạ

入力は文字列の配列です。

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

使い方

f2\Ạ  Main link. Argument: A (array of strings)

 2\   Pairwise reduce by:
f       Filter, yielding all chars in the left string that appear in the right one.
   Ạ  All; yield 1 if all strings are non-empty, 0 if not.


12

網膜25 20バイト

(.).*¶(?=.*\1)

^.+$

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

次の数字にも出現する数字を見つけるたびに、それらの数字の間の区切り文字を削除します(前の数字の数字とともに、共有数字から始まりますが、それは無関係です)。プロセスですべての区切り文字が削除されている場合、入力は有効です。文字列が1行として一致することを確認することにより、区切り文字を確認します。


11

Brachylog、9バイト

{⊇ᵐ=∧?t}ˡ

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

これは整数のリストだけでなく、文字列のリストまたはリストのリストでも機能することに注意してください。

説明

{      }ˡ       Left fold on the input:
 ⊇ᵐ=              It is possible to find a number which is a subset of both input numbers
    ∧             (and)
     ?t           The output is the second number (to continue the fold)

2
カッコいい。宣言的?言語に仕様を伝えているだけのようです。
発癌性

3
@Carcigenicate Brachylogは確かに宣言的であり、宣言的論理プログラミング言語Prologに基づいています。
致命的

2
私の無制限の自由時間に達したときに学ぶために、実際に私の(ますます)長い言語のリストにあるプロローグ。クールな言語が多すぎます!
発癌性

8

JavaScript(ES6)、47 44 * 43バイト

@Neilのおかげで1バイト節約

x=>x.every(y=>y.match(`[${p}]`,p=y),p=1/19)

入力を文字列のリストとして受け取ります。

テストスニペット

* 取り消し線44はまだ通常の44です


動作し`[${p}]`ませんか?
ニール

@Neil各配列の最初の項目ではありません。
-ETHproductions

ああ、私はあなたが回避策を見つけたのを見ます。私はa=>a.reduce((l,r)=>`${l}`.match(`[${r}]`)&&r)(数値入力でも機能する)まで持っていました。
ニール

おそらくp&&設定すると削除できますp=1/19か?
ニール

@ニールI、ええと...まあ...それは天才です、ありがとう:
ETHproductions

6

05AB1E、10バイト

ü‚vy`Så1åP

オンラインでお試しください! またはテストスイートとして

説明

ü‚          # map pairing over each pair in input
  v         # for each pair
   y`       # push as 2 separate elements on stack
     Så     # check each digit in 2nd number for membership in first
       1å   # check if any 1 exists in the resulting list
         P  # product of stack

€Sü.å-これが思ったように機能したことを願っています。
魔法のタコUr

@carusocomputing:ええ、それは素晴らしかったでしょう。または単にü.åまたは€Süå
エミグナ

なぜドットコマンドでペアワイズが再び機能しないのですか?
魔法のタコUr

1
@carusocomputing:次のバイトをコマンドとして使用するためにのみ実装されています。ドットは考慮されません。
エミグナ

6

CJam18 15 14バイト

Martin Enderのおかげで4バイト節約

l~Afb_1>.&:,:*

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

説明

l~              e# Read and eval the input
  Afb           e# Convert each number to a list of digits
     _          e# Duplicate the array
      1>        e# Slice it after the first element
        .&      e# Vectorized set intersection; take the set intersection of corresponding 
                e#  elements of the two arrays
          :,    e# Get the length of each intersection
            :*  e# Take the product of the whole array. 
                e#  Will be 0 if any intersection was empty.

6

Haskell、51 48 35バイト

@NickHansenのおかげで-3バイト!これらのモナド演算子で本当に良くなる必要があります

-4バイトと-9バイトは、それぞれ@Laikoniと@nimiのおかげです!

and.(zipWith(any.flip elem)=<<tail)

このバージョンは、入力を文字列の配列として受け取り、の必要性を排除しますがshow、見た限りでは、古いバージョンとほぼ同じように機能します。

all(\(x,y)->any(`elem`x)y).(zip=<<tail).map show

(このような匿名関数を送信できることはかなり確かですが、必要に応じて修正します)

まず、数値が文字列に変換されます。次に、モナドマジックzip=<<tailは、リストをそれ自体で圧縮する関数を作成します。この関数は、各エントリとその近隣をペアにします。次にall、ラムダを各ペアにマッピングし、1つの文字列に他の文字列が含まれているかどうかをチェックし、最後にすべてが出力されることをチェックしTrueます。

基本的に同じ方法で動作する古いバージョン:

f a=and$zipWith(\b->any(`elem`show b).show)a$tail a

私はzipといくつかの(->)モナドトリックを使用してバイトを剃ることができました:f(x、y)= any( 'elem'x)y; g = all f。(zip = << tail).map show 。編集:elemは(できれば明らかに)バックティックにあるべきですが、それはコメントフォーマッタでは不可能です。
ニックハンセン

44バイト:and.(zipWith(any.flip elem)=<<tail).map show
ライコニ

たとえば["1234567890", "19", "95", "5012", "23"]、入力を文字列のリストとして取得することが許可されているため、をドロップできます.map show
-nimi

5

Mathematica 62 47 35バイト

MartinEのおかげで12バイトが節約されました。

FreeQ[#⋂#2&@@@Partition[#,2,1],{}]&

FreeQ[#⋂#2&@@@Partition[#,2,1],{}]&[{{1},{1,2},{2,0,3},{0},{3,1}}]

FreeQ[#⋂#2&@@@Partition[#,2,1],{}]&[{{1},{1,2},{2,0,3},{0},{3,0}}]

本当


4

ルビー、49 48バイト

->x{x.each_cons(2){|z|x&&=z*' '=~/(.).* .*\1/};x}

出力はnilfalseで、trueの「ランダム」整数です。


4

Java 8、94 90 87バイト

入力は、数字を表す文字列の配列です。2番目の文字列から開始し、前の各文字列に対して正規表現の比較を実行して、文字が含まれているかどうかを確認します.*[previous string].*

ゴルフ:

a->{int r=1,i=0;while(++i<a.length)r*=a[i].matches(".*["+a[i-1]+"].*")?1:0;return r>0;}

ゴルフをしていない:

public class NumberChainingPredicate {

  public static void main(String[] args) {
    System.out.println("Expect true:");
    for (String[] input : new String[][] { { "1", "1", "1", "11", "111", "11", "1" }, { "12", "23", "34", "45", "56" },
        { "65", "54", "43", "32", "21" }, { "123", "29", "9", "59", "55", "52", "2017", "2" },
        { "1234567890", "19", "95", "5012", "23" } }) {
      System.out.println(java.util.Arrays.toString(input) + " = " + exec(f(), input));
    }

    System.out.println();
    System.out.println("Expect false:");
    for (String[] input : new String[][] { { "1", "2", "3", "4", "5", "1", "11" }, { "12", "23", "33", "45" },
        { "98", "87", "76", "11", "12", "23" } }) {
      System.out.println(java.util.Arrays.toString(input) + " = " + exec(f(), input));
    }
  }

  private static java.util.function.Function<String[], Boolean> f() {
    return a -> {
      int r = 1, i = 0;
      while (++i < a.length) {
        r *= a[i].matches(".*[" + a[i - 1] + "].*") ? 1 : 0;
      }
      return r > 0;
    };
  }

  private static boolean exec(java.util.function.Function<String[], Boolean> function, String[] input) {
    return function.apply(input);
  }

}

いいね!私が投稿しようとしていたよりもはるかに短い..とにかく、あなたはもう少しゴルフをすることができます:a->{for(int i=1;i<a.length;)if(!a[i].matches(".*["+a[i++-1]+"].*"))return 0>1;return 1>0;}90バイト
ケビンCruijssen

私もそれを90にゴルフしましたが、別の方法で:a->{int r=1;for(int i=0;++i<a.length;)r*=a[i].matches(".*["+a[i-1]+"].*")?1:0;return r>0;}
ビジネス猫

1
気にせず、87になった:a->{int r=1,i=0;for(;++i<a.length;)r*=a[i].matches(".*["+a[i-1]+"].*")?1:0;return r>0;}
ビジネスキャット

両方に感謝します。これを意味のある量だけ改善する唯一の方法は正規表現を見ることだと思います。

4

ゼリー、6バイト

Dµf"ḊẠ

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

説明

Dµf"ḊẠ
Dµ        Treat the first (i.e. only) input as a list of decimal digits
   "      For each pair of corresponding elements in {the input digits} and
    Ḋ     {the input digits} with the first element removed
  f       take all elements common to both sides
     Ạ    then return true if the result has no empty lists, false otherwise

これは、使用しようとする最も明白なのです2/ここで、それはサイズ2のすべてのスライスに単項関数を実行し"Ḋ効果的に実行バイナリ我々が使用できることを意味し、隣接する要素のすべてのペアの機能、fむしろ単項に変換する必要よりも(直接にとして機能しますf/)。これにより、入力の最後の要素がそのまま残りますが、幸運なことに、0の入力でさえ10進数に変換しても空のリストにならないため、には影響しません




3

05AB1E、5バイト

コード:

üÃõå_

CP-1252エンコードを使用します。オンラインでお試しください!またはすべてのテストケースを検証してください!

説明:

üà         # Intersection on each pair
  õå       # Check if the empty string exists
    _      # Boolean negate

なんてこった!RüÃõå_自分で思いついたものでした。あなたの最高の答えにとても近く、私のものを削除できたことを光栄に思います。なぜ必要ないのRですか?
魔法のタコUr

1
@carusocomputingうーん、何のRためですか?:p
アドナン

2

PowerShell、87バイト

param($n)(1..($a=$n.length-1)|?{[char[]]$n[($i=$_)-1]|?{$n[$i]-like"*$_*"}}).count-eq$a

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

どんな手段でも最短ではありませんが、他の人が使用しているアプローチとは少し異なるアプローチであり、気の利いた|?{}機能を示しています。

これは、入力を文字列の配列として受け取り、$nから1までループしますlength-1Where-Object|?{...})を使用して、特定の条件に当てはまるインデックスを引き出します。これforは、if句のある組み合わせループのように考えることができます。

ここの節は[char[]]$n[($i=$_)-1]|?{$n[$i]-like"*$_*"}です。つまり、現在のインデックスを取得し、それを$_に設定し$i、を減算し1、それを使用してインデックスを作成します$n(つまり、入力配列の前の要素を取得します)。次に、これはchar-array としてキャストされ、別のWhere-Objectプロシージャを介して送信されます。

内側の句の$n[$i]-like"*$_*"現在のインデックスにある文字列があることを指定し$iている-like現在の文字$_以前のインデックスから。したがって、これにより、2つの配列要素間で共通する文字が出力されます。したがって、共通の文字が存在する場合(PowerShellで空の配列が偽であるため)のみ、外側の句は真実であるため、共通の文字がある場合にのみインデックスが選択されます。

次に、基準に一致したすべてのインデックスを収集し、そのインデックスが入力配列の長さに合っている.countことを確認し-eqます。そのブール結果はパイプラインに残り、出力は暗黙的です。



2

APL(Dyalog APL)、9バイト

∧/×≢¨2∩/⎕

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

∧/ リストのすべてのもの

× しるし

 の集計

¨ それぞれの

2∩/ のペアワイズ交差点

 入力?


「記号」の意味はわかりませんが、すべての数字が正の値になると仮定できます。
発癌性

@Carcigenicateそれらはまたゼロである場合もあります。
アダム

うん、ごめん。「非負」。
発癌性

2

PHP、65 68

for(;null!==$a=$argv[++$i+1];)$r+=$a==strtr($a,$argv[$i],_);echo!$r;

すべての数値を反復処理し、前に現れたすべての数字を削除します。数値自体に等しい回数を数えます(数字は削除されません)。少なくとも1つが等しければ、ペアの1つで一致しませんでした。


triminsted of を使用した間違いを修正しましたstrtr。@JörgHülsermannに感謝


すみません。指定されたテストケースに対して、ソリューションは機能します。["filename",1,11,414]動作しません。
ヨルグヒュルサーマン

@JörgHülsermannは、必ずtrim先頭と末尾の文字に対してのみ機能します。それを修正しました。
クリストフ

PHP <7.1の場合a&null!==(-5バイト)の代わりに使用できます。
タイタス

...しかし、これはの最初の数字でのみ機能します。$argv[$i]「fromとtoの長さが異なる場合、2つのうち長い方の余分な文字は無視されるからです。」(マニュアルより)
Titus

2

PHP、75バイト

for($b=3**39;--$argc;)preg_replace("#[$b]#","",$b=$argv[$argc])<$b?:die(1);

コマンドライン引数から数値を取得します。で終了1とfalsyため、0truthyため。オンラインで
実行する-r、オンラインでテストします

  • で始まる$b=すべての数字を含む数字
  • 引数をループダウンします
    • $b引数からすべての数字を削除します
    • 引数をコピーします $b
    • 数字が削除されなかった場合、終了 1
  • 暗黙的:で終了 0

1

PHP、77バイト

for($i=$t=1;++$i<$argc;)$t*=preg_match("#[{$argv[$i-1]}]#",$argv[$i]);echo$t;

1
代替:foreach($argv as$k=>$v)$t=$k--?$t*preg_match("#[{$argv[$k]}]#",$v)):1;echo$t;、77バイト(未テスト)。
イスマエルミゲル

1
@IsmaelMiguel Heavyの代替案まず、1つに変更$k----$kてドロップする必要があります)、その後、アプローチが機能し、警告に@を追加する必要があります
ヨルグヒュルサーマン

ああ、はい、構文エラーを引き起こす役に立たない括弧に気付きませんでした。そして、私は同意しません$k--。最初の実行で$ kがまだ0になるように具体的に使用しました。また、警告は無視できます。つまり、コードは現在76バイトですが、まだテストされていません。
イスマエルミゲル

編集後、それが正常に機能してforeach($argv as$k=>$v)$t=$k--?$t*preg_match("#[{$argv[$k]}]#",$v):1;echo$t;いることを確認できます。テスト$argv = array(1, 12, 123, 3, 34, 45, 5, 5);を表示 1し、テストで$argv = array(1, 12, 123, 3, 34, 45, 5, 6);ディスプレイ0予想通り、。
イスマエルミゲル

@IsmaelMiguelの最初のパラメーターはファイル名であることを忘れます。
ヨルグヒュルサーマン

1

MATL、14バイト

1&)"V@VX&nv@]x

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

バイトを保存してくれた@LuisMendoに感謝します。説明:

1&)            % 'Pop' the first item from the input and push it on the stack.
   "       ]   % Main 'for' loop, to loop over the rest of the input.
    V            % Stringify previous (or first) iten from the input.
     @V          % Push current number, convert to string
       X&        % Intersect with stringified number already on the stack.
         nv      % Count the size of the intersection, and add it to the existing list of sizes.
           @     % Push the current number again for the intersection in the next loop. 
             x % Remove the number pushed by the last loop.
               % Else the program would end with the result on the second instead of the first position in the stack

バイトを置き換え1)VGて保存できます1&)(これにより、最初の数字を繰り返す必要がなくなります)
ルイスメンドー

@LuisMendoもちろん!MATLにはこの機能があることを漠然と思い出しましたが、仕様で「ポップ」(キューやスタックなど)を検索しても結果が得られなかったため、間違っていると思いました。
-Sanchises

はい、実際には参照インデックスの特定のケースです。2つの出力の場合、次のような参照インデックス操作)により、選択された値が最初の出力として、残りの値が2番目の出力として与えられます
ルイスメンドー

@LuisMendo賢い。MATLABを改善するためにMATLを雇う必要があります...
Sanchises

ハハ。MATLABでこれらの機能の一部が見落とされることがあります
ルイスメンドー

1

Clojure、71バイト

(fn[n](every?(fn[[q w]](some q w))(partition 2 1(map #(set(str %))n))))

数字のシーケンスを受け入れる匿名関数。true/を返しますfalse

読み方が好きです。ここで改善できる領域は間違いなくいくつかあります。渡される私の関数mapは簡単に変更できないため、関数マクロを必要としません。つまり、関数全体がいくつかのバイトを追加した可能性のあるマクロを使用できません。また、every?述語の値を展開するより良い方法を見つけ出せたら嬉しいです。

(defn number-chain? [nums]
  (let [; Turn each number into a set of characters
        set-nums (map #(set (str %)) nums)

        ; Partition the sets into lists of neighbors
        ; [1 2 3 4] -> [[1 2] [2 3] [3 4]]
        partitioned (partition 2 1 set-nums)]

    ; Does every second neighbor contain some element of the first?
    (every?
      (fn [[l1 l2]]
        (some l1 l2))
      partitioned)))

1

SimpleTemplate、124バイト

うわー、これはトレーニングでした!

{@eachargv asA keyK}{@ifK}{@setR"/[",O,"]/"}{@calljoin intoR"",R}{@ifA is notmatchesR}{@return}{@/}{@/}{@setO A}{@/}{@echo1}

これは「単純に」古い要素を使用して正規表現を作成1し、真の値として表示するか、それ以外の場合は何も表示しません。


ゴルフをしていない:

{@each argv as number key K}
    {@if K}
        {@set regex "/[", old, "]/"}
        {@call join into regex "", regex}
        {@if number is not matches regex}
            {@return false}
        {@/}
    {@/}
    {@set old number}
{@/}
{@echo 1}

1

JavaScript(ES6)、37バイト

s=>/^(.*(.).*\n(?=.*\2))+.+$/.test(s)

入力を改行区切りの文字列として受け入れます。@ MartinEnder♦の優れたRetina回答に基づきますが、JavaScriptの方が短いため、テスト全体を単一の正規表現で実行します。


1

ピップ12 10バイト

$&B@X^_MPg

入力を一連のコマンドライン引数として受け取ります。出力は、真の場合は空でないリストであり、偽の場合は空のリストです。オンラインそれを試してみたり、すべてのテストケースを確認してください

説明

         g  List of all cmdline args
       MP   Map this function to consecutive pairs of items from that list:
     ^_      Split 1st item of pair into list of characters
    X        Convert to regex that matches any of those characters
  B@         Find all matches in 2nd item of pair
$&          Fold on logical AND--truthy if all items are truthy, falsey if one is falsey
            Print (implicit)

1

ローダ45 35バイト

{[_=~`(\S*(\S)\S* (?=\S*\2))+\S+`]}

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

これは、Martin EnderによるRetinaソリューションの移植版であるPerl 5ソリューションに似ています。@Neilのおかげで-10バイト。

別のソリューション(73 72バイト)を次に示します。

{[_/""]|{|x|{x|[0]()unless[not(_ in y)]else[1]}if tryPeek y}_|sum|[_=0]}

これは、ストリームから文字列を取得し、連続する文字列に同じ文字が含まれていることを確認する匿名関数です。説明:

{
    [_/""]|    /* split strings -> creates arrays of characters */
    {|x|       /* begin for loop over character arrays */
        {      /* begin if tryPeek(y) -> peeks the second item from the stream */
               /* x and y are now two consecutive character arrays */
            x| /* push characters in x to the stream */
            [0]()unless[not(_ in y)]else[1] /* pushes 0 to the stream */
                                            /* if y contains the character */
                                            /* in the stream, otherwise 1 */
        }if tryPeek y
    }_|        /* end for loop */
    sum|       /* sum all numbers in the stream */
    [_=0]      /* return true if the sum is zero */
}

もっとゴルフができるかもしれない...


一度にテスト全体を実行する単一の正規表現を使用すると役立ちますか?のようなもの^(\S*(\S)\S* (?=\S*\2))+\S+$
ニール

@Neilそれはうまくいくようです。ありがとう!
fergusq

1

Bash + Unixユーティリティ、71 69バイト

sed "s/\(.*\)/<<<\1 \&\&grepx[\1]/;1s/.*g/g/;\$s/ .*//"|tr 'x
' \ |sh

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

入力は標準入力で、1行に1つの数字が入ります。

出力は終了コードにあります:0は真実、1は偽です。

これはおそらくもっとゴルフできるでしょう。

上記のコードが機能するためには、現在のディレクトリに名前が1桁のファイルは存在できません。これが受け入れられない場合は[\1]、プログラムで'[\1]'(2バイトの追加コストで)を置き換えます。

サンプルの実行(チャレンジで提供された最後のテストケース):

$ echo '98
> 87
> 76
> 11
> 12
> 23' | ./digittest > /dev/null; echo $?
1

(1ここは偽です。)


使い方:

上記のサンプルでデモを行います。

sedコマンドは、入力を次のように変換します。

grepx[98]
<<<87 &&grepx[87]
<<<76 &&grepx[76]
<<<11 &&grepx[11]
<<<12 &&grepx[12]
<<<23

次に、trコマンドはこれを文字列に変換します。

grep [98] <<<87 &&grep [87] <<<76 &&grep [76] <<<11 &&grep [11] <<<12 &&grep [12] <<<23

この文字列は、目的の操作を実行するためのシェルコマンドなので、shにパイプして完了です。


ファイルの制限は問題ありませんが、それは確かに奇妙な制限です。
発癌性

1

Q、57バイト

{r::();({r,::any(last x)in y;x,enlist y}\)($)0,x;all 1_r}
  1. グローバルrを初期化します。
  2. 入力を文字列の配列に変換します。
  3. 配列をスキャンして、最後の文字列の一部の文字が現在の文字列にあることを確認します。
  4. 各結果をrに追加します。
  5. すべての文字列がステップ3を満たす場合は1を返し、そうでない場合は0を返します。

注:関数内の入力配列の先頭に0が追加されます。これは、最初の要素の比較が参加して行われるように行われました。それ以外の場合、比較のために最初の要素の最後の文字が取得されます。ただし、現在のカウントに7バイトを追加する型チェックを実行できます。


これは、Clojureの回答と同様のアプローチのようです。きちんとした言語。
発がん性
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.