コードのナゲット


18

コードのナゲット

それはだそれは仮定の状況金曜日の夜、あなたの好きな趣味に参加するために通常のゴルフ仲間の上に招待した:コードゴルフ。ただし、これは非常に頭脳流出の作業であるため、コードから可能な限りゴルフをできるように、グループの脳の食べ物を手に入れる必要があります。

今、みんなのお気に入りのスナックはチキン・ナゲットですが、問題があります:みんなのニーズを満たす単一のパックはありません。だから、あなたはすでにゴルフのムードにいるので、すべてのナゲットのニーズを満たすために購入しなければならないパックを正確に把握するプログラムを作成することにします。

チキンナゲットパックのサイズはいたるところにあり、世界のどこに住んでいるかによって標準サイズも変わります。ただし、最も近い[ナゲットを提供する場所]では、次のサイズのナゲットパックを在庫しています。

4, 6, 9, 10, 20, 40

これで、ナゲットの特定の組み合わせを注文できないことに気付くかもしれません。たとえば、正確に11等しい組み合わせがないため、ナゲットは不可能です11。ただし、431パック20、1パック10、1パック9、1パック4

20 + 10 + 9 + 4 = 43 (597)

ここ597で、各項は二乗されて加算されます(ヒント:最適なソリューションではこれが最高値になります)。もちろん、他の作成方法もあり43ますが、ご存知のように、パックあたりのナゲットが多いほど、ナゲットごとに安くなります。したがって、コストを最小限に抑えるために、理想的には最小数のパックを最大数で購入する必要があります。

タスク

各人の要件に対応する整数のリストを取得するプログラムまたは関数を作成する必要があります。次に、チキンナゲットを購入するための最もコスト効率の高いα注文を計算して印刷する必要があります。最もコスト効率の高いα次数は、各数量の二乗和が最高になる組み合わせです。完全にナゲットを購入する方法は絶対に存在しない場合、あなたがしなければならない印刷などfalsy値を、、、またはあなたの言語で利用可能であるものは何でも。0FalseImpossible!

I / Oの例:

[2 7 12 4 15 3] => [20 10 9 4]
     1, 1, 2, 1 => False
  6 5 5 5 5 5 9 => 40
      [6, 4, 9] => 9 10
              1 => 0
            199 => 40, 40, 40, 40, 20, 10, 9
              2 => Impossible!

以下は、最初の400の理想的なソリューションのリストです。これらは、あなたの期待通りにフォーマットされていないことに注意してください。それぞれtupleはの形式(N lots of M)です。

ルール

  1. 標準的な抜け穴はありません。
  2. FrobeniusSolveMathematica など、タスクのすべてまたは大部分を実行する組み込み関数は使用しません。

α-これを例で明確にするために、を行うことで43を作成することもできますが4 + 6 + 6 + 9 + 9 + 9 = 43 (319)、これは最適ではなく、したがって、平方和が導入部で述べた組み合わせよりも小さいため、誤った出力になります。基本的に、平方和が大きいほどコストが低くなり、コスト効率が最も高くなります。


時間/メモリの制限はありますか?
デニス

@Dennis時間やメモリの制限はありません。
カーデ

4
実は木曜日です。
mbomb007

4
@ mbomb007 Astuteobservation:Pイントロを調整しました。
ケード

2
私が使用する必要がある鶏が定理をmcnugget ...何とか
ストレッチマニアック

回答:


7

Pyth、26 25バイト

e+Zo.aNf!-TCM"  
("./sQ

印刷できない文字がいくつかあることに注意してください。オンラインで試してください:デモンストレーション。それは非常に遅いです(しかし、私の26バイトのソリューションほど遅くはありません)。

説明:

                          implicit: Q = input list
                     sQ   sum(Q)
                   ./     generate all integer partitions
       f                  filter for partitions T, which satisfy:
             "   ("          string containing chars with the ASCII-values of 4,6,9,10,20,40
           CM                convert each char to the ASCII-value
         -T                  remove this numbers from T
        !                    and check, if the resulting list is empty
    o                      order the remaining subsets N by:
     .aN                      the vector length of N (sqrt of sum of squares)
  +Z                       insert 0 at the beginning
 e                         print the last element

Pyth、32バイト

e+Zo.aNfqsTsQysm*]d/sQdCM"  
(

印刷できない文字がいくつかあることに注意してください。オンラインで試してください:デモンストレーション このバージョンははるかに高速です。[6,7,8]約1秒で入力の解を見つけ、[30]約90秒で入力の解を見つけます。

説明:

                                 implicit: Q = input list
                          "...(  the string containing chars with the ASCII-values of 4,6,9,10,20,40
                        CM       convert each char to the ASCII-value
                m                map each number d to:
                  ]d                create the list [d]
                 *  /sQd            and repeat it sum(Q)/d times
               s                 unfold
              y                  generate all subsets
        f                        filter for subsets T, which satisfy:
         qsTsQ                      sum(Q) == sum(T)
    o                            order the remaining subsets N by:
     .aN                            the vector length of N (sqrt of sum of squares)
  +Z                             insert 0 at the beginning
 e                               print the last element

なぜ合計ではなく、平方和の平方根によるのですか?
mbomb007

1
@ mbomb007それは問題ではないからです。a> bの場合、sqrt(a)> sqrt(b)の場合、またはその逆。そして、この.a方法を使用することは、二乗して合計するよりも短いですs^R2
ジャクベ

5

Perl、175 153

sub f{my$n=$_[0];if(!$n){return 1;}foreach$o(40,20,9,10,6,4){if($n>=$o&&f($n-$o)){print"$o ";return 1;}}return 0;}$n+=$_ for@ARGV;if(!f($n)){print":(";}

プログラムの引数から入力を受け取ります。完璧な解決策が見つからない場合は:(を出力します。

未ゴルフコード:

sub f
{
    my $n = $_[0];
    if(!$n)
    {
        return 1;
    }
    foreach $o(40,20,9,10,6,4)
    {
        if($n>=$o&&f($n-$o))
        {
            print "$o ";
            return 1;
        }
    }
    return 0;
}

$n += $_ for @ARGV;
if(!f($n))
{
    print ":(";
}

PS:これはおそらく1 2;)に10分はかからない最初のエントリです。

こちらをご覧ください。


これまでで最速のプログラムと思われるものをおめでとうございます!それは私の参照プログラムよりも速いかもしれません:P私はあなたの投稿の下部にイデオンリンクを追加して、人々が出力を見ることができるようにしました。
カデ

コードが誤った出力を生成する可能性があります。入力で189 9なく、印刷する必要があります4 4 10
デニス

他にも誤った出力があります。間違っていない場合は、9との順序を入れ替えることで、それらすべてを修正できます10
デニス

@Dennisありがとう、修正しました!
トーマスオルトマン

3

CJam、45 29 28バイト

q~:+_[40K9A6Z)U]m*_::+@#=0-p

このアプローチは非常に遅く、メモリを集中的に使用することに注意してください。

CJamインタープリターでオンラインで試してください。

5バイトのコストで大幅に高速化できます。

q~:+_40/4+[40K9A6Z)U]m*_::+@#=0-p

入力の合計の複雑さは依然として指数関数的ですが、これはオンラインインタープリターで最大159、Javaインタープリターで最大199のテストケースを数秒で処理するはずです。

CJamインタープリターでオンラインで試してください。

考え

最適な購入(正方形の最大の合計)は、多くとして持つ有効な購入(ナゲットの正しい数)である40「が多くて、可能な限りの20その後、多くの可能な限りs」は、9の可能な限り(例えば、9 9あります好ましいオーバー10 4 4)などのために10の、6 'sおよび4「S。

このアプローチでは、N個の配列のコピー[40 20 9 10 6 4 0]のデカルト積を生成します。ここで、Nは希望するナゲットの数です。Nは、必要な購入数の(悪い)上限です。コードの高速バージョンでは、代わりにN / 40 + 4を使用します。

配列の順序付けのため、デカルト積はベクトル[40 ... 40]で始まり、ベクトル[0 ... 0]で終わります。正しい合計(最適な平方和も含む)を持つ最初のベクトルのインデックスを計算し、対応する配列要素を取得し、プレースホルダーとして機能するゼロを削除して結果を出力します。

ベクトルが見つからなかった場合、インデックスは-1になるため、[0 ... 0]を取得し、代わりに空の配列を出力します。

コード

q~                            e# Read from STDIN and evaluate the input.
  :+                          e# Push N, the sum of all elements of the resulting array.
     [40K9A6Z)U]              e# Push B := [40 20 9 10 6 4 0].
    _           m*            e# Push B**N, the array of all vectors of dimension N
                              e# and coordinates in B.
                  _::+        e# Copy and replace each vector by its sum.
                      @#      e# Get the first index of N.
                        =     e# Retrieve the corresponding element.
                         0-p  e# Remove 0's and print.

これは:)かかわらず、高速なコードの仕上げをさせるよりもなり手によって溶液から取り組んでいくつかの状況のいずれか...いい仕事かもしれ
カーデ

2

ジュリア、126バイト

r->(t=filter(i->all(j->j[4,6,9,10,20,40],i),partitions(sum(r)));show(!isempty(t)&&collect(t)[indmax(map(k->sum(k.^2),t))]))

これにより、入力として配列を受け入れ、ソリューションが存在するかどうかに応じて、STDOUTに配列またはブール値を出力する名前のない関数が作成されます。呼び出すには、名前を付けf=n->...ます。

Ungolfed +説明:

function f(r)
    # Nugget pack sizes
    packs = [4, 6, 9, 10, 20, 40]

    # Filter the set of arrays which sum to the required number of nuggets
    # to those for which each element is a nugget pack
    t = filter(i -> all(j -> jpacks, i), partitions(sum(r)))

    # Print the boolean false if t is empty, otherwise print the array of
    # necessary nugget packs for which the sum of squares is maximal
    show(!isempty(t) && collect(t)[indmax(map(k -> sum(k.^2), t))])
end

例:

julia> f([1])
false

julia> f([2,7,12,4,15,3])
[20,10,9,4]

1

Python 3-265文字

import itertools as i
n=list(map(int,input().split(',')));m=[]
for f in range(1,9):
 for j in range(6*f):
  for x in i.combinations((4,6,9,10,20,40,)*f,j+1):
   if sum(n)==sum(x):m.append(x)
if m!=[]:v=[sum(l**2for l in q)for q in m];print(m[v.index(max(v))])
else:print(0)

間隔の表示:

import itertools as i
n=list(map(int,input().split(',')));m=[]
for f in range(1,5):
 for j in range(6*f):
\tfor x in i.combinations((4,6,9,10,20,40,)*f,j+1):
\t if sum(n)==sum(x):m.append(x)
\t\tif m!=[]:v=[sum(l**2for l in q)for q in m];print(m[v.index(max(v))])
else:print(0)

すべてのテストケースに合格

注:非常に遅いため、これがすべてのケースをパスするかどうかはわかりません...しかし、そうすべきです...


今のところこれで何も問題はありません。テストして確認します。家に帰ってから、Gistにあるリストを生成するために使用した、参照のないプログラムを追加します。私はタイミングを計っていませんでしたが、すべてのケースで8〜12分の範囲でかかったと思います。
ケード

@ Vioz-ブリリアント!:D
ベータ崩壊

私が間違っているように見えますが、36をテストした後、MemoryErrorに遭遇する前に約4,000万の組み合わせ(正確には40,007,602)を通過します。4GBのメモリしかないため、これは私の作業マシンの制限かもしれません。
ケード

Vioz-フム...まあ、私は自分の携帯電話上でのテストを遂行することは絶望的だ... @
ベータ崩壊

1
@undergroundmonorail一度だけ使用する場合は、4文字未満の場合、まっすぐにインポートする方が適切です(5分割も可能)。ただし、複数回使用する場合from blah import*は常に最適です。上記について考えることができる唯一の例外は、複数importのを持っている場合です。これは、as実際にどこが役立つかを頭に浮かぶ唯一の時間です。
Sp3000

1

JavaScript、261 256 261

d="length";function g(a){for(z=y=0;y<a[d];z+=+a[y++]);return z}x=[40,20,10,9,6,4];l=prompt().split(",");o=g(l);p=[];for(i=0;i<x[d];i++)r=g(p),s=r+x[i],(s<o-3||s==o)&&p.push(x[i]),(i==x[d]-1||40<o-r)&&r+x[i]<o-3&&(i=-1,0==i||o-r<p[p[d]-1]&&p.pop());g(p)==o&&p||0

これでいいかどうかはわかりませんが、うまくいくようですが、間違いなく見逃しています。

しかし、それは遅くないように見えますが、それまで123456[40 x 3086, 10, 6]ほとんど即座に出力します。

説明:

ナゲットサイズの反復(最初に最大)

  • スタックとナゲットのサイズの合計が目標より小さい場合-3->スタックにプッシュする
  • 残りが40個を超える場合->ループカウンターをリセットする
  • スタックの合計が最後のナゲットサイズに達したときに目標よりも大きい場合->最後の要素をポップし、ループカウンターをリセットします
  • スタックの合計が加算される場合はそれを返し、そうでない場合は0を返します

199 | 1構築されたスタックは次のようになります

i | stack
0   [40]
0   [40, 40]
0   [40, 40, 40]
0   [40, 40, 40, 40]
0   [40, 40, 40, 40]
1   [40, 40, 40, 40, 20]
2   [40, 40, 40, 40, 20, 10]
3   [40, 40, 40, 40, 20, 10, 9]
4   [40, 40, 40, 40, 20, 10, 9]
5   [40, 40, 40, 40, 20, 10, 9]
==> [40, 40, 40, 40, 20, 10, 9]

1

i | stack
0   []
1   []
2   []
3   []
4   []
5   []
==> 0

1
あなたのアプローチは、目標を達成できるかどうかをチェックしていないようです。11印刷し[6]18印刷し[10, 4]ます。
デニス

@Dennisやあ、指摘してくれてありがとう。昨日は深夜でした。5文字修正しました。18個[10,4]のかっこがありませんでした。チェックは確かに間違っていました。結果セットに少なくとも1つの要素が含まれているかどうかをチェックしました。私はそこに何を考えたのか分からない
-C5H8NNaO4
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.