この値は、一意のコインやメモで作成できますか?


29

整数として入力された金銭的価値が、コインや紙幣の一意の組み合わせで表現できるかどうかを計算するプログラムを作成します。これは、同じコイン/紙幣を複数回使用できないことを意味します。

プログラムは入力として値を取る必要があり、入力または言語の配列に相当するものを介してコイン/紙幣の値のリストを取ることができます。硬貨/紙幣のリストは変更できるはずですので、定数を使用している場合は、これがどこで定義されているかを明確にしてください。

プログラムは、真偽値を出力する必要があります。

値を構成する硬貨/紙幣のリストを出力する必要はないことに注意してください。

英国ポンドを使用(£1.00 = 100および£420.69 = 42069)

coins = [1, 2, 5, 10, 20, 50, 100, 200, 500, 1000, 2000, 5000]

以下はtrueを出力します:

6 (1, 5)
15 (10, 5)
88 (1, 2, 5, 10, 20, 50)
512 (500, 10, 2)
7003 (5000, 2000, 2, 1)

以下はfalseを出力します:

4
209
8889
4242424242
[ANYTHING ABOVE 8888]

代替試験データ(米ドル)

coins = [1, 5, 10, 25, 50, 100, 200, 500, 1000, 2000, 5000, 10000]

がんばろう!


4
あなたのような新人がもっといるといいのですが…
リーキー・ヌン


2
別のコインセットを使用していくつかのテストケースを追加する必要があります
リーキー修道女

2
私は、最大で未使用のコイン、つまり最大で残りの値を取るという貪欲なヒューリスティックでは解決できないテストケースを追加することをお勧めします。また、入力がソートされておらず、値を複数の方法で作成できるものを用意しておくとよいでしょう。一般に、テストケースは、誰かがテストケースで機能する問題に対して、すべてを正しく理解せずに合理的に試行する可能性を回避するのに適しています。
xnor

2
関連関連する。前者の質問はほぼ間違いなく重複していますが、この質問はIMOの方が適切に設計されており、重複として閉じる場合は、古い質問を閉じます。

回答:


13

Brachylog 2(TIO Nexus)、2バイト

⊇+

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

標準入力または配列リテラルとしてプログラムの先頭に追加することにより、コインのリストを取得します(どちらでも機能しますので、「より合法」だと感じるのはあなた次第です;前者はデフォルトで許可されています) PPCGルール、後者は質問で特に許可されています); そして、生成する値をコマンドライン引数として受け取ります。

説明

このプログラムは、Trare NexusのBrachylog関数のラッパーの実装の詳細を利用します。具体的には、コマンドライン引数を指定して、出力を介して入力を指定できます。(これはBrachylogの元の設計では想定されていませんでしたが、PPCGでの実装によって言語が定義されているため、実装が必要に応じて実行される場合、それを利用できます。)プログラムは次のようになります。

⊇+
⊇   Some subset of {standard input}
 +  sums to {the first command-line argument}

完全なプログラムとして、ブール値を返します。true.プログラム内のすべてのアサーションを同時に満たすことができる場合、または満たすfalse.ことができない場合。

(リマインダー、またはまだ知らない人のために:Brachylog 2は、長さが1バイトの独自の文字エンコーディングを使用します。)


⊇はBrachylogの1バイトであると言ったのに、なぜこのバイトをここに貼り付けないのですか?それには理由があると思うが、私はただ興味があるだけで、文字をエンコードするナブのビットだ。
-theonlygusti

1
彼らは次のようにディスク上に符号化されている08 2B(あなたはエンコーディングを調べることができ、ここで)。特定のエンコードをリストしなかった理由は、それが無関係だからです。本当に重要なのは、Brachylogが使用する一意の文字が256個以下であるため、それぞれが1バイトで表現できることです。これは一般的に、コードを読みやすくするためにゴルフ言語によって行われます。代わりにコードページ437のようなエンコーディングを使用できますが、それを行うと誰も読むことができません

10

05AB1E、4バイト

æOså

説明:

æ      Calculate the powerset of the first input
 O     Sum each element
  s    Put the second input at the top of the stack
   å   Check whether the input is in the powerset sum.

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


あなたは公式にリストを圧縮するように全員を誤解させたように見えます; p
リーキーヌン

あなたが圧縮されたリストを削除し、入力にそれを移動した後、私は(時間によって、私たちの答えは同じになるので)私の答えを削除します
漏れ修道女

このコミュニティは天才だらけです。
トビ

5

Mathematica、25バイト

!FreeQ[Tr/@Subsets@#,#2]&

最初の引数としてコイン値の配列を取り、2番目の引数としてターゲット整数を取り、Trueor を返す純粋な関数False



3

網膜52 31バイト

\d+
$*
^((1+) |1+ )+(?<-2>\2)+$

オンラインでお試しください!入力をスペースで区切られたコインとメモのリストとして受け取り、その後に目的の値が続きます。編集:私のコードをデバッグした@Kobiのおかげで18バイトを節約しました。説明:最初の2行は、単に10進数から単項に変換します。3行目は、コインとメモのリストをキャプチャします。交替により、エンジンはバックトラックし、特定のコイン/ノートをキャプチャしないことを選択できます。次に、バランスグループは、値をキャプチャリストのすべてのサフィックスと照合します(不要ですがゴルファーです)。


エンジンは長さ0のグループにバックトラックしないため、2番目のオプションは機能しません(迷惑な最適化)。使用できます^((1+) )+(\2?(?<-2>)|){99}$(34バイト、コイン数の制限付き)、または^((1+) |1+ )+(\2?(?<-2>))+$(34バイト)。
コビ

1
@Kobi Beautiful!私はそれを忘れてしまったので、両方の回答から2バイトを保存し(?<-2>\2?)、さらに2番目の回答から?もう1バイトを保存しました。
ニール


2

Java(OpenJDK 8)、125バイト

boolean f(int[]c,int n){int l=c.length;if(l<1)return n==0;int[]a=java.util.Arrays.copyOf(c,l-1);return f(a,n-c[l-1])|f(a,n);}

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


ラムダでこれを行うと、短くなります。
Okx

@Okx再帰的であるため(より長くなります)、ラムダが短くなってもラムダは実行しません。
リーキー修道女

1
アルゴリズムの反復バージョンは、配列をコピーする必要がないため、はるかに短くなります:boolean f(int[]c,int n){for(int l=c.length;l-->0;n-=n<c[l]?0:c[l]);return n<1;}(79バイト)。Java 8とそのラムダでは、さらに62バイトに減らすことができます。現在のあなたの答えを考えると、代わりにint l=c.length-1使用するlことl-1も短くなります。
オリビエグレゴワール


2

JavaScript(ES6)、81 69 67 64バイト

カリー化構文でコインのリストcと目標額aを取得します(c)(a)0またはを返しますtrue

c=>g=(a,m=1)=>c.map((c,i)=>x-=c*(m>>i&1),x=a)&&!x||x-a&&g(a,m+1)

テストケース


コインのリストを取得できますか?
リーキー修道女

@LeakyNun「...そしてコイン/紙幣の値のリストを取得できる...」
マーティン・エンダー

1
だから私は...何のためにリストをエンコード
漏れ修道女に

@LeakyNunそうですね
エディ・ハート

2

Haskell、28バイト

演算子関数(#)は、整数と整数のリスト(または、より一般的には、Traversable数値のコンテナー)を取り、を返しますBool

として使用し6#[1, 2, 5, 10, 20, 50, 100, 200, 500, 1000, 2000, 5000]ます。

c#l=elem c$sum<$>mapM(:[0])l

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

使い方

  • c希望の値とlコインの値のリストです。
  • mapM(:[0])lmap (:[0])over l、各値を0とペアにして、デカルト積を構築し、各要素がの対応する値lまたは0であるリストを提供します。
  • sum<$>各組み合わせを合計し、結果のリストにあるelem c$かどうかを確認しますc

2

R、88 83バイト

@Jarko Dubbeldamのおかげで-5バイト

無名関数を返します。コインの可能なすべての組み合わせを生成し(のexpand.gridペアで使用T,F)、値が存在するかどうかをチェックします。Rの予約語であるため、kコインcです。一度に複数の値をチェックできます。

function(k,v)v%in%apply(expand.grid(Map(function(x)!0:1,k)),1,function(x)sum(k[x]))

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


あなたは置き換えることができますc(T,F)することによって!0:1、およびrep(list(!0:1),length(k))によってlapply(k,function(x)!0:1)
JAD

1
実は、それを作るMap(function(x)!0:1,k)
JAD

1

Japt、7バイト

à mx èN

オンラインでお試しください!0falsyの出力、真実の正の整数。

説明

à mx èN
          // Implicit: U = input array, V = input integer, N = array of all inputs
à         // Take all combinations of U.
  mx      // Map each combination to its sum.
     è    // Count the number of items in the result which also exist in
      N   //   the array of inputs.
          // This returns 0 if no combination sums to V, a positive integer otherwise.
          // Implicit: output result of last expression


1

ルビー、39バイト

nil偽の値として返されます。また、リスト内で最小のコインの値を返します。これは、Rubyですべての数値が真実であることを示します。

f=->c,n{n!=0?c.find{|i|f[c-[i],n-i]}:1}

ただし、このアルゴリズムは非常に遅く、O(C!)時間の複雑Cさがあるため、コインリストの長さは注意してください。最終的には終了しますが、ほとんどのテストケースは、ほとんどのオンラインインタープリターでもタイムアウトになりますf(UK_POUND, 5)

これは、終了条件を追加することでより速く終了し、実際にタイムアウトするのがはるかに難しい41バイトのバージョンです

f=->c,n{n>0?c.find{|i|f[c-[i],n-i]}:n==0}

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


1

Bash + GNUユーティリティ、56 39

printf %$2s|egrep "^ {${1//,/\}? {}}?$"

入力金種リスト(ソートなし)はコンマ区切りリストとして指定されます。入力リストと値は、コマンドラインパラメーターとして指定されます。

シェルの戻りコードの形式で指定された出力。echo $?スクリプトの実行後に検査します。 0真実を1意味し、偽りを意味します。

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

  • printf %$2svalueスペースの文字列を出力します
  • "^ {${1//,/\}? {}}?$"は、金種リストをのような正規表現に展開するシェル展開です^ {1}? {2}? {5}? {10}? ... $egrep正規表現エンジンは、宗派の順序に関係なく、これと正しく一致するほどスマートであることが判明しました
  • egrep スペースの文字列が正規表現と一致するかどうかをチェックします

1

C、66バイト

m;v;f(n){for(m=1e5;m/=10;)for(v=5;n-=n<v*m?0:v*m,v/=2;);return!n;}

ここ動作することを確認してください

C、53バイト

g(c,w,n)int*c;{for(;n-=n<c[--w]?0:c[w],w;);return!n;}

このバリアントはコイン配列を使用しますが、単純な減算に帰着するため、この問題の目的を無効にします。

最初の引数はコイン配列、2番目はコイン数、3番目は値です。

C、48バイト

g(c,n)int*c;{for(;n-=n<*c?0:*c,*++c;);return!n;}

前のバリアントの代替。コイン配列を逆にしてゼロで終端できることを前提としています。



0

CJam18 17バイト

q~_,2\m*\f.*::+#)

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

説明

q~                  e# Read and eval input.
  _,                e# Duplicate the money list and take its length.
    2\m*            e# Take the (length)th Cartesian power of [0 1].
        \f.*        e# Element-wise multiplication of each set of 0's and 1's with the money
                    e#   list. This is essentially the powerset, but with 0s instead of 
                    e#   missing elements.
            ::+     e# Sum each set.
               #    e# Find the index of the desired amount in the list. (-1 if not found)
                )   e# Increment. -1 => 0 (falsy), anything else => nonzero (truthy)




0

Mathematica、42バイト

ListQ@NumberDecompose[#,Sort[#2,Greater]]&

入力

[15、{10,5}]

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