निर्धारित करें कि क्या एक सिक्का प्रणाली कैनोनिकल है


48

खजांची एल्गोरिथ्म है कि ज्यादातर मुद्रा प्रणाली के लिए काफी अच्छी तरह से काम करता है सिक्कों की न्यूनतम संख्या में परिवर्तन करने के लिए एक एल्गोरिथ्म है। हालांकि अधिकांश लालची एल्गोरिदम की तरह यह इसके दोषों के बिना नहीं है। यदि एक मुद्रा प्रणाली को सही (या सिर्फ गलत) स्थापित किया गया है तो कुछ निश्चित मूल्य हैं, जिसमें कैशियर का एल्गोरिथ्म इष्टतम परिवर्तन खोजने में विफल रहेगा।

निम्नलिखित उदाहरण लें:

हमारे पास 4 ¢, 3 ¢, और 1 ¢ सिक्के हैं। हम 6 ¢ बनाना चाहते हैं।

कैशियर के एल्गोरिथ्म पहले सबसे बड़े सिक्के (शुरू करने के लिए एक 4 gorith) और घटाना और दोहराने के रूप में कई का चयन करेंगे। इसके परिणामस्वरूप कुल 4 सिक्कों के लिए एक 4 and सिक्का और दो 1 in सिक्के होंगे।

दुर्भाग्य से एल्गोरिथ्म के लिए केवल दो सिक्कों (दो 3) सिक्कों) के साथ 6 m बनाने का एक तरीका है।

सभी पूर्णांक मूल्यों के लिए परिवर्तन की एक प्रणाली को विहित विचार माना जाएगा, कैशियर के एल्गोरिथ्म में सिक्कों की इष्टतम संख्या मिलेगी।

कार्य

आप एक सिस्टम को या तो एक अनियंत्रित कंटेनर के रूप में लेना चाहते हैं या सिक्का मूल्यों का प्रतिनिधित्व करने वाले पूर्णांकों के क्रमबद्ध कंटेनर को क्रमबद्ध करते हैं और यदि सिस्टम इनपुट विहित और मिथ्या है तो एक सत्य मान का उत्पादन करते हैं।

आपका कार्यक्रम सभी प्रणालियों के लिए काम करना चाहिए जो किसी भी मूल्य का निर्माण कर सकते हैं। (अर्थात सभी प्रणालियों में 1) का सिक्का होगा)

यह कोड गोल्फ कम से कम बाइट्स जीतता है।

परीक्षण के मामलों

यह सूची संपूर्ण माध्यम से नहीं है, आपके प्रोग्राम को सभी मान्य इनपुट के लिए काम करना चाहिए

1, 3, 4       -> 0
1, 5, 10, 25  -> 1
1, 6, 10, 25  -> 0
1, 2, 3       -> 1
1, 8, 17, 30  -> 0
1, 3, 8, 12   -> 0
1, 2, 8, 13   -> 0
1, 2, 4, 6, 8 -> 1

@ जीबिट्स हर मामले में इसका मतलब यह नहीं है कि यह अंतर सबसे छोटे सिक्के से सबसे बड़े सिक्के के बराबर बढ़ता या बराबर होता है
Jörg Hülsermann

@ JörgHülsermann यह वास्तव में बहुत अच्छा नहीं है। [१, ६, १३] का अंतर बढ़ता जा रहा है, लेकिन यह अभी भी ६ * ३ के बजाय १ 13 (१३ + १ * ५) जैसी किसी चीज पर विफल है।
ज्योबिट्स

16
इन्हें Canonical Coin Systems कहा जाता है । यह छोटा कागज एक बहुपद-समय एल्गोरिथ्म की जाँच के लिए देता है कि क्या एक सिक्का प्रणाली कैनोनिकल है (हालांकि एक कम कुशल विधि गोल्फ हो सकती है)। एक दिलचस्प परीक्षण मामले से 37 सेंट कर रहा है 25, 9, 4, 1(से इस math.SE पद ) - भले ही प्रत्येक सिक्का छोटे की राशि से बड़ा है, गैर लालची 25, 4, 4, 4लालची धड़कता है 25, 9, 1, 1, 1
xnor

1
@xnor ध्यान दें कि 9, 4, 1-> एक 4, 4, 4बेहतर 9, 1, 1, 1उदाहरण है।
isaacg

जवाबों:


9

हास्केल, 94 87 82 बाइट्स

f s=and[j i-2<j(i-x)|let j i=last$0:[1+j(i-x)|x<-s,x<i],i<-[1..2*last s],x<-s,x<i]

यह समाधान एक फ़ंक्शन को परिभाषित करके काम करता है jजो कैशियर के एल्गोरिथ्म का प्रदर्शन करता है और हमें बताता है कि कैशियर कितने सिक्कों का उपयोग करता है। हम सूची में दो बार सबसे बड़ी संख्या तक की जांच करते हैं, यह मानते हुए कि सिस्टम सभी पिछले संख्याओं के लिए विहित है, कि सबसे बड़ा संभव सिक्का लेना सही विकल्प है।

यह समाधान मानता है कि इनपुट सॉर्ट किया गया है।

दो बार सबसे बड़ी संख्या तक सबूत की जांच पर्याप्त है: यह मान लें कि सिस्टम कुछ संख्या के लिए विहित नहीं है i, और kसूची में सबसे बड़ी संख्या से अधिक नहीं होने दें i। मान लें कि i >= 2kऔर सिस्टम सभी संख्याओं से कम के लिए विहित है i

iसिक्कों को बनाने का कुछ इष्टतम तरीका है , और मान लें कि इसमें सिक्का नहीं है k। यदि हम सिक्कों में से एक को फेंक देते हैं, तो सिक्कों का नया योग इससे बड़ा kऔर छोटा होना चाहिए i- लेकिन इस नंबर पर कैशियर के एल्गोरिथ्म में kसिक्के का उपयोग होगा - और इसलिए, सिक्कों के इस सेट को सिक्कों के बराबर सेट के साथ बदला जा सकता है। सिक्का युक्त k, और इसलिए kसंख्या के लिए सिक्का युक्त सिक्कों का एक सेट है i, और प्रेरण द्वारा खजांची के एल्गोरिथ्म इष्टतम विकल्प देता है।

यह तर्क वास्तव में दिखाता है कि हमें केवल दो सबसे बड़े तत्वों की राशि तक जांच करने की आवश्यकता है - लेकिन ऐसा करना लंबा है।

संपादित करें: fiverjan जोहान्सन की बदौलत पांच बाइट्स!


1
आप letइसके बजाय का उपयोग करके एक बाइट बचा सकते हैं where। आप इसे या तो |let ...पैटर्न गार्ड के रूप में f s, या सूची की समझ के अंदर रख सकते हैं ।
अर्जन जोहान्सन

1
एक और चार बाइट्स के साथ j i=last$0:[1+j(i-k)|k<-s,k<i]
अर्जन जोहान्सन

5

पायथ, 18 15 बाइट्स

!x#eST.gsky_S*e

परीक्षण सूट

एक अलग तरह की पाशविक ताकत। यह प्रत्येक के k के साथ सिक्कों के सभी संग्रह बनाने से शुरू होता है, जहां k सबसे बड़ा सिक्का है, जिसे अंतिम सिक्का माना जाता है। मेरा मानना ​​है कि हमेशा एक ही राशि के दो सेट बनाने के लिए यह पर्याप्त है, एक लालची और एक छोटा, जब भी ऐसी जोड़ी मौजूद हो।

मैं फिर इस तरह की जोड़ी का पता लगाता हूं:

सबसेट बढ़ते आकार के क्रम में उत्पन्न होता है, और इनपुट में स्थिति के आधार पर दूसरी तरह से। सिक्का संग्रह उनके समूह द्वारा, कड़ाई से करें। प्रत्येक सिक्का संग्रह अवरोही क्रम में उत्पन्न होता है, इसलिए लालची समाधान समूह का पहला तत्व होगा यदि और केवल अगर लालची समाधान इष्टतम है, और यह समूह का अंतिम तत्व है। इस प्रकार, हम समूह में नॉनज़रो इंडेक्स पर लालची समाधान और फ़िल्टर पाते हैं। यदि सिक्का सेट तोप का है, तो यह सब कुछ फ़िल्टर कर देगा, इसलिए हम बस परिणाम और आउटपुट को तार्किक रूप से नकार देते हैं।

स्पष्टीकरण:

!x#eST.gsky_S*e
!x#eST.gsky_S*eQQ   Variable introduction.
                    Q = eval(input()) - sorted list of coins.
              eQ    Greatest coin in the list
             *  Q   Repeat that many times.
            S       Sort the coins
           _        Reverse, so we have the coins in descending order.
          y         Form all subsets, in increasing size then
                    decreasing lexicographic order.
      .gsk          Group by sum
 x#                 Filter by the index in the group of
   eST              The last element lexicographically (greedy solution).
!                   Logically negate.

बहुत अच्छा - किसी भी विचार के लिए यह 1, 2, 4, 6, 8] के लिए हरकुप्प पर लटका हुआ है और टीआईओ के साथ मारा जाता है /opt/tryitonline/bin/pyth: line 5: 28070 Killed ... Exit code: 137? बस स्मृति से बाहर?
जोनाथन एलन

यह मेमोरी के 2 ^ (संख्या सिक्के * अंतिम सिक्का) बाइट्स का उपयोग करता है। तो आपके उदाहरण के लिए, 2 ^ 40। RAM की एक टेराबाइट के साथ कई मशीनें नहीं हैं
isaacg

मैंने सोचा कि ऐसा हो सकता है, एल्गोरिथ्म का वर्णन समझ में आता है, लेकिन मैंने संख्याओं की गणना नहीं की थी - इतनी जल्दी इतनी बड़ी!
जोनाथन एलन

5

PHP, 323 बाइट्स

अन्य तरीके से समान तरीके से सिक्कों को तब तक गिनते हैं जब तक कि दो अंतिम तत्व सरणी में न हों

<?function t($g){rsort($g);$m=array_slice($g,1);for($y=1,$i=$g[0];$i<$g[0]+$m[0];$i++){$a=$b=$i;$p=0;$r=$s=[];while($a||$b){$o=$n=0;$g[$p]<=$a?$a-=$r[]=$g[$p]:$o=1;($m[$p]??1)<=$b?$b-=$s[]=$m[$p]:$n=1;$p+=$o*$n;}$y*=count($r)<=count($s);}return$y;}for($i=0,$t=1;++$i<count($a=$_GET[a]);)$t*=t(array_slice($a,0,$i+1));echo$t;

मेरा सबसे अच्छा और सबसे लंबा जवाब मुझे विश्वास है> 370 बाइट्स

मैं केवल एक विस्तारित संस्करण देता हूं क्योंकि यह लंबे समय तक है तो मेरा जवाब पहले

for($x=1,$n=0,$f=[];++$n<count($a)-1;){
$z=array_slice($a,0,$n+1);
$q=$a[$n]-$a[$n-1];
$i=array_fill(1,$c=max($a[$n+1]??1,11),"X");#$q*$a[$n]
$f=range($a[$n],$c,$q);

$f[]=2*$a[$n];
for($d=[$z[$n]],$j=0;$j<$n;){
   $f[]=$a[$n]+$d[]=$z[$n]-$z[$j++]; 
}

while($f){
    $i[$t=array_pop($f)]="T";
    foreach($d as $g)
    if(($l=$t+$g)<=$c)$f[]=$l;
}

foreach($i as$k=>$v){
    if(in_array($k,$z))$i[$k]="S";
}
#var_dump($i);
if($i[$a[$n+1]]=="X")$x*=0;
}
echo$x;

इस उत्तर के लिए स्पष्टीकरण

ऑनलाइन संस्करण

  1. सभी को सरणी में गलत == X पर सेट करें

  2. आपके द्वारा S को नियंत्रित की गई सरणी में सभी संख्याएँ सेट करें

  3. अंतिम S और अन्य S या 0 के बीच अंतर पाया गया

  4. सरणी में अंतिम S पर प्रारंभ करें

  5. सभी संख्याओं को सभी अंतरों में से एक, जहां डी लास्ट एस + में सेट करें

  6. सभी डी पर शुरू करें

  7. सरणी में D मानों के लिए "T" सेट करें

  8. गोटो 5 इसे सभी डीआई के साथ दोहराएं यह वास्तव में कोड में नहीं था

  9. अगर अगले आइटम में ऐरे में X है तो यह एक और गलत मामला है

अतिरिक्त चरण अंतर स्निपेट में मामले में 3 है 1 और 4 के बीच 2 एक्स हैं इसका मतलब है कि आपको चरण 5 द्वारा दूसरे डी की आवश्यकता है। इस मामले में इस मूल्य के बाद 10 सभी मामले सच हैं मैं अब तक देख सकता था कि एक रिश्ता है अंतर और सरणी में गिनती के बीच आप गणना करते हैं कि अंतिम झूठे मामले को खोजने से पहले आपको कितना डी (चरण 5) प्राप्त करने की आवश्यकता है।

आप अंतिम आइटम से सीधे सही पर कई मान सेट करते हैं। ये पॉइंट्स यह तय करने के लिए एक अंतर बना सकते हैं कि क्या यह हो सकता है कि अगले मूल्य वाले सिक्कों की लालची गिनती समान हो तो सरणी में अंतिम के कई। दूसरे रास्ते पर आप दुश्मन को सेट कर सकते हैं

  1. 1 + अंतिम एस पर पहला दुश्मन सेट करें

  2. इस बिंदु से अगले दुश्मनों को सेट करने के लिए सरणी में प्रत्येक मान जोड़ें

  3. अंतिम दुश्मन गोटो 2 से शुरू करें

यदि आपके पास अब शत्रु और सच्चे मामले हैं, तो संभावना बढ़ती है कि गिनती अधिक हो सकती है और अधिक डी के साथ संभावना डूब जाती है।

table{width:80%}
td,th{width:45%;border:1px solid blue;}
<table>
  <caption>Working [1,4]</caption>
<tr><th>Number</th><th>Status</th></tr>
<tr><td>1</td><td>S</td></tr>
<tr><td>2</td><td>X</td></tr>
<tr><td>3</td><td>X</td></tr>
<tr><td>4</td><td>S</td></tr>
<tr><td>5</td><td>X</td></tr>
<tr><td>6</td><td>X</td></tr>
<tr><td>7</td><td>D3</td></tr>
<tr><td>8</td><td>D4</td></tr>
<tr><td>9</td><td>X</td></tr>
<tr><td>10</td><td>D3D3</td></tr>
<tr><td>11</td><td>D4D3</td></tr>
<tr><td>12</td><td>D4D4</td></tr>
<tr><td>13</td><td>D3D3D3</td></tr>
<tr><td>14</td><td>D4D3D3</td></tr>
<tr><td>15</td><td>D4D4D4</td></tr>
<tr><td>16</td><td>D4D4D3</td></tr>
</table>
<ul>
  <li>S Number in Array</li>
  <li>D Start|End point TRUE sum Differences from last S</li>
  <li>X False</li>
  </ul>

प्लस? बाइट्स शुक्रिया @JonathanAllan मुझे गलत टेस्ट केस देने के लिए
262 बाइट्स लगभग नहीं लेकिन काफी अच्छे हैं 4 पल में गलत टेस्टकेस

झूठे के बाद सच होने से पहले परीक्षण मामलों [1,16,256]

<?for($q=[1],$i=0,$t=1,$w=[0,1];++$i<count($a=$_GET[v]);$w[]=$a[$i],$q[]=$m)($x=$a[$i]-$a[$i-1])>=($y=$a[$i-1]-$a[$i-2])&&((($x)%2)==(($m=(($a[$i]+$x)*$a[$i-1])%$a[$i])%2)&&$m>array_sum($q)||(($x)%2)==0&&(($a[$i]-$a[$i-2])*2%$y)==0||in_array($m,$w))?:$t=0;echo$t;

आरोही का क्रम

व्याख्या

for($q=[1],$i=0,$t=1,$w=[0,1] # $t true case $q array for modulos $w checke values in the array
;++$i<count($a=$_GET[v])   #before loop
;$w[]=$a[$i],$q[]=$m) # after loop $q get the modulo from the result and fill $w with the checked value

($x=$a[$i]-$a[$i-1])>=($y=$a[$i-1]-$a[$i-2]) 
# First condition difference between $a[i] and $a[$i-1] is greater or equal $a[$i-1] and $a[$i-2]
# if $a[$-1] == 1 $a[$i-2] will be interpreted as 0
&&  ## AND Operator with the second condition
(
(($x)%2)==   # See if the difference is even or odd
(($m=(($a[$i]+$x)*$a[$i-1])%$a[$i])%2)&&$m>array_sum($q)
# After that we multiply the result with the lower value *$a[$i-1]
    # for this result we calculate the modulo of the result with the greater value %$a[$i]
    # if the difference and the modulo are both even or odd this belongs to true
# and the modulo of the result must be greater as the sum of these before
    # Ask me not why I have make try and error in an excel sheet till I see this relation
||
(($x)%2)==0&&(($a[$i]-$a[$i-2])*2%$y)==0 # or differce modulator is even and difference $a[$i],$a[$i-1] is a multiple of half difference $a[$i-1],$a[$i-2] 
||
in_array($m,$w) # if the modulo result is equal to the values that we have check till this moment in the array we can also neglect the comparison
)
?:$t=0; # other cases belongs to false
echo$t; #Output

ऐसा लगता है कि मैंने जो तालिका देखी है उसमें [1,2,3,4,5,6] से मान शामिल हैं और मैं केवल अंतिम आइटम को 9 तक बदलता हूं। 2to3 और 4to5 के लिए हम निम्न मान का मान बनाते हैं। modulo गणना

table{width:95%;}th,td{border:1px solid}
<table><tr><th>difference</th><td></td><td>1</td><td>1</td><td>1</td><td>1</td><td>1</td></tr>
<tr><th>difference modulo 2</th><td></td><td>1</td><td>1</td><td>1</td><td>1</td><td>1</td></tr>
<tr><th>value</th><td>1</td><td>2</td><td>3</td><td>4</td><td>5</td><td>6</td></tr>
<tr><th>result</th><td></td><td>3</td><td>8</td><td>15</td><td>24</td><td>35</td></tr>
<tr><th>modulo value great</th><td></td><td>1</td><td>2</td><td>3</td><td>4</td><td>5</td></tr>
<tr><th>modulo 2</th><td></td><td>1</td><td>0</td><td>1</td><td>0</td><td>1</td></tr>
<tr><th></th><td></td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><th>difference</th><td></td><td>1</td><td>1</td><td>1</td><td>1</td><td>2</td></tr>
<tr><th>difference modulo 2</th><td></td><td>1</td><td>1</td><td>1</td><td>1</td><td>0</td></tr>
<tr><th>value</th><td>1</td><td>2</td><td>3</td><td>4</td><td>5</td><td>7</td></tr>
<tr><th>result</th><td></td><td>3</td><td>8</td><td>15</td><td>24</td><td>45</td></tr>
<tr><th>modulo value great</th><td></td><td>1</td><td>2</td><td>3</td><td>4</td><td>3</td></tr>
<tr><th>modulo 2</th><td></td><td>1</td><td>0</td><td>1</td><td>0</td><td>1</td></tr>
<tr><th></th><td></td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><th>difference</th><td></td><td>1</td><td>1</td><td>1</td><td>1</td><td>3</td></tr>
<tr><th>difference modulo 2</th><td></td><td>1</td><td>1</td><td>1</td><td>1</td><td>1</td></tr>
<tr><th>value</th><td>1</td><td>2</td><td>3</td><td>4</td><td>5</td><td>8</td></tr>
<tr><th>result</th><td></td><td>3</td><td>8</td><td>15</td><td>24</td><td>55</td></tr>
<tr><th>modulo value great</th><td></td><td>1</td><td>2</td><td>3</td><td>4</td><td>7</td></tr>
<tr><th>modulo 2</th><td></td><td>1</td><td>0</td><td>1</td><td>0</td><td>1</td></tr>
<tr><th></th><td></td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><th>difference</th><td></td><td>1</td><td>1</td><td>1</td><td>1</td><td>4</td></tr>
<tr><th>difference modulo 2</th><td></td><td>1</td><td>1</td><td>1</td><td>1</td><td>0</td></tr>
<tr><th>value</th><td>1</td><td>2</td><td>3</td><td>4</td><td>5</td><td>9</td></tr>
<tr><th>result</th><td></td><td>3</td><td>8</td><td>15</td><td>24</td><td>65</td></tr>
<tr><th>modulo value great</th><td></td><td>1</td><td>2</td><td>3</td><td>4</td><td>2</td></tr>
<tr><th>modulo 2</th><td></td><td>1</td><td>0</td><td>1</td><td>0</td><td>0</td></tr></table>


", "जब आप अलग हो सकते हैं तो आप क्यों विभाजित होते हैं ","; जब आप सूची ले सकते हैं तो आप विभाजित क्यों होते हैं; जब आप एक क्रमबद्ध सूची ले सकते हैं तो आप क्यों छाँटते हैं? (यदि आप जिस विधि का उपयोग कर रहे हैं वह अचूक है, तो मैं अभी भी अनिश्चित हूं, क्या आपके पास कोई प्रमाण है, क्योंकि जिस साहित्य के माध्यम से मैंने स्किम्ड किया है, यह सुझाव देने से लगता है कि यह कठिन है कि मुझे लगता है कि आपका कोड क्या कर रहा है।)
जोनाथन एलन

@ JörgHülsermann क्षमा करें, अगर मैंने कोई भ्रम पैदा किया है, हालाँकि यह अलग था, इससे पहले कि आप ऐसा कर सकें तो अब आप एक क्रमबद्ध सूची ले सकते हैं।
गेहूं जादूगर

मुझे डर है कि मुझे लगता है कि आपको मतभेदों पर सिर्फ मॉड 2 से अधिक परीक्षण करना होगा, उदाहरण के [1,2,5,11,17]लिए विहित। हो सकता है कि मेरे उत्तर से जुड़े कागज पर एक नज़र डालें।
जोनाथन एलन

... और सिर्फ इसकी पुष्टि करने के लिए गर्व हैसेलकर के कोड के बजाय मेरा: ideone.com/C022x0
जोनाथन एलन

@HeatWizard [1,2,5,11,17] सही या गलत है?
जोर्ग हल्सरमन

4

जावास्क्रिप्ट (ईएस 6), 116 125 130

l=>eval("r=(d,k)=>d?--k&&l.map(v=>v>d||r(d-v,k)):x=1;for(x=l[0]*2;--x>1;r(x,g))g=0,h=x,l.map(v=>(g+=h/v|0,h%=v));x")

यह अवरोही क्रम में क्रमबद्ध इनपुट सरणी की जरूरत है। 2N से प्रत्येक मान 2 के लिए (एन अधिकतम सिक्का मूल्य जा रहा है), यह लालची एल्गोरिथ्म से सिक्कों की संख्या का पता लगाता है और सिक्कों के एक छोटे सेट को खोजने का प्रयास करता है।

कम गोल्फ वाला

l=>{
  // recursive function to to find a smaller set of coins
  // parameter k is the max coin limit
  r = (d,k) => d // check if difference is not 0
     ? --k // if not, and if the number of coins used will be less than limit
      && l.map(v => v>d || r(d-v, k))  // proceed with the recursive search
     : x=1 // if diff is 0, value found, set x to 1 to stop the loop
  for( x=l[0]*2; --x > 1; )  
    g=0, h=x, l.map(v=>(g += h/v|0, h %= v)), // find g with the greedy algorithm
    r(x,g) // call with initial difference equal to target value
  return x
}

परीक्षा

f=
l=>eval("r=(d,k)=>d?--k&&l.map(v=>v>d||r(d-v,k)):x=1;for(x=l[0]*2;--x>1;r(x,g))g=0,h=x,l.map(v=>(g+=h/v|0,h%=v));x")

/* No eval
f=l=>{
  r=(d,k)=>d?--k&&l.map(v=>v>d||r(d-v,k)):x=1;
  for(x=l[0]*2;--x>1;r(x,g))
    g=0,h=x,l.map(v=>(g+=h/v|0,h%=v));
  return x;
}*/

;[
 [[100,50,20,10,5,2,1],1], [[4,3,1],0],
 [[25,10,5,1],1], [[25,10,6,1],0],
 [[3,2,1],1], [[30,17,8,1], 0], 
 [[12,8,3,1],0], [[13,8,2,1], 0]
].forEach(t=>{
  var i=t[0],k=t[1],r=f(i),
      msg=((r==k)?'OK ':'KO ')+i+' -> '+r
      + (r==k?'':' (should be '+k+')')
  O.textContent += msg+'\n'
})

function test()
{
  var i=I.value.match(/\d+/g).map(x=>+x).sort((a,b)=>b-a)
  O.textContent = i+' -> '+f(i)+'\n'+O.textContent
 }
#I { width:50% }
<input id=I value='1 4 9'><button onclick='test()'>test</button>
<pre id=O></pre>


4

पायथन, 218 211 205 बाइट्स

-1 बाइट धन्यवाद @TuukkaX (एक जगह के बीच <3और हटाया जा सकता है or)

from itertools import*
g=lambda x,c,n=0:x and g(x-[v for v in c if v<=x][0],c,n+1)or n
lambda c:len(c)<3or 1-any(any(any(x==sum(p)for p in combinations(c*i,i))for i in range(g(x,c)))for x in range(c[0]*2))

repl.it

अवरोही क्रम में इनपुट।

बुरी तरह से क्रूर बल। एकल इकाई सिक्के का कोई सेट और कोई अन्य सिक्का विहित है। बड़े सेटों के लिए सबसे छोटी असफलता का मामला, यदि कोई मौजूद है, तो वह 3 जी सबसे छोटे सिक्के के बराबर या उससे अधिक होगा (यह सुनिश्चित नहीं है कि यह कैसे बराबर हो सकता है!) और दो सबसे बड़े सिक्कों के योग से कम है - इस पेपर को देखें (जो वास्तव में है) एक और संदर्भ देता है, लेकिन एक O (n ^ 3) विधि भी देता है।

g लालची विधि द्वारा उपयोग किए जाने वाले सिक्कों को गिना जाता है, और अनाम फ़ंक्शन संभावित उम्मीदवारों का पता लगाता है (वास्तव में 0 से एक से दो बार बाइट्स को बचाने के लिए सबसे बड़ा सिक्का) और कम सिक्कों के किसी भी संग्रह की तलाश करता है जो उस राशि के लिए भी योग करता है।

gखजांची क्या करता है, यह प्रदर्शन करता है, यह पुनरावृत्ति करता है कि सबसे बड़ा सिक्का कम से कम या उससे अधिक राशि के बराबर होता है जो अभी भी ऊपर, [v for v in c if v<=x][0]दूर, और उपयोग किए गए सिक्कों की संख्या को गिनता है n

अनाम फ़ंक्शन 1 लौटाता है यदि len(c)3 से कम है, और अन्यथा परीक्षण करता है कि ऐसा नहीं है, तो यह है 1-...कि संभावनाओं की श्रेणी में कोई भी मान range(c[0]*2))), कम सिक्कों के साथ संभव है, i in range(g(x,c))हर सिक्के के कई में से एक संग्रह बनाकर, c*i, और iसिक्कों के सभी संयोजनों की जांच combinations(c*i,i)करने के लिए, यह देखने के लिए कि क्या एक ही मूल्य का योग है।


@WheatWizard ने [13,8,2,1] के लिए गलत रिटर्न दिया - मैंने इसे परीक्षण मामलों में जोड़ा। जोड़ा स्पष्टीकरण कि इनपुट अवरोही क्रम में है।
जोनाथन एलन

1
3orकार्य करना चाहिए।
यति

धन्यवाद @TuukkaX, मैं भी not(...)साथ बदल सकता है1-...
जोनाथन एलन

2

जेली ( कांटा ), 15 14 बाइट्स

SRæFµS€Ṃ=$Ṫµ€Ȧ

यह समाधान इस पेपर से काउंटर-उदाहरणों के लिए सीमा का उपयोग करता है । वहां, लेखक काउंटर-उदाहरण के लिए एक तंग बाउंड का उपयोग करता है, लेकिन गोल्फिंग के हितों में, सिक्का संप्रदायों के योग की सीमा का उपयोग किया जाता है जो बड़ा होता है और इसमें बाध्य होता है।

यह कार्यक्रम मेरी मशीन पर एक से भी कम समय में सभी परीक्षण मामलों की गणना करता है।

दुर्भाग्य से, यह जेली की एक शाखा पर निर्भर करता है जहां मैं एक फ्रोबेनियस हल परमाणु को लागू करने पर काम कर रहा था ताकि आप इसे ऑनलाइन करने की कोशिश न कर सकें।

प्रयोग

$ ./jelly eun 'SRæFµS€Ṃ=$Ṫµ€Ȧ' '1,2,4,6,8'
1

प्रदर्शन अच्छा है और एक सेकंड से भी कम समय में सभी परीक्षण मामलों को हल कर सकते हैं।

$ time ./jelly eun 'SRæFµS€Ṃ=$Ṫµ€Ȧ¶Ç€' '[[1,3,4],[1,5,10,25],[1,6,10,25],[1,2,3],[1,8,17,30],[1,3,8,12],[1,2,8,13],[1,2,4,6,8]]'
[0, 1, 0, 1, 0, 0, 0, 1]

real    0m0.793s
user    0m0.748s
sys     0m0.045s

व्याख्या

SRæFµS€Ṃ=$Ṫµ€Ȧ  Input: list of integers C
    µ           Start a new monadic chain
S                 Sum
 R                Range, [1, 2, ..., sum(C)]
  æF              Frobenius solve for each X in the range using coefficients from C
                  This generates all vectors where the dot product of a
                  vector with C equals X, ordered by using values from the
                  start to end of C
           µ€   Start a new monadic chain that operates on each list of vectors
     S€           Sum each vector
         $        Monadic hook on the sums
       Ṃ            Minimum (This is the optimal solution)
        =           Vectorized equals, 1 if true else 0
          Ṫ       Tail (This is at the index of the greedy solution)
             Ȧ  All, returns 0 if it contains a falsey value, else 1

2

जावास्क्रिप्ट (ईएस 6), 144 132 124 122 110 बाइट्स

a=>![...Array(a[0]*2)].some((_,i)=>(g=(a,l=0,n=i)=>[a.filter(c=>c>n||(l+=n/c|0,n%=c,0)),-l*!n])(...g(a))[1]>0)

सरणी को अवरोही क्रम में क्रमबद्ध करने की आवश्यकता है। लिंक किए गए पेपर में अवलोकन का उपयोग करता है कि यदि प्रणाली विहित नहीं है, तो कम से कम एक मान 2a [0] से कम होता है, जो प्रारंभिक लालची एल्गोरिथ्म से अप्रयुक्त सिक्कों का उपयोग करके विघटित होने पर कम सिक्के लेता है।

संपादित करें: 12 बाइट्स को यह महसूस करके सहेजा गया कि मैं सभी सिक्कों की जांच कर सकता हूं, भले ही मैं पहले से ही लक्ष्य मूल्य तक पहुंच गया हूं। मेरे मध्यवर्ती आउटपुट को से स्विच करके 8 बाइट्स सहेजे [l,b]गए [b,-l]; इसने मुझे पहला परिणाम सीधे दूसरी कॉल के पैरामीटर के रूप में पास करने की अनुमति दी, साथ ही दूसरी बचत सफल रही या नहीं, यह भी एक छोटी बचत है। की परिभाषा को ले जाकर 2 बाइट्स सहेजा gमें someकॉलबैक, मुझे अनावश्यक रूप से दो बार पाश चर में गुजर से बचने के लिए अनुमति देता है। मेरे पुनरावर्ती सहायक फ़ंक्शन से कॉल पर filter(मेरे मध्यवर्ती आउटपुट स्विच द्वारा संभव बनाया गया) पर स्विच करके 12 बाइट्स सहेजे गए।


2

पर्ल, 69 बाइट्स

के लिए +2 शामिल है -pa

STDIN पर अवरोही क्रम में सिक्के दें। आप वैकल्पिक रूप से 1सिक्के को छोड़ सकते हैं ।

coins.pl <<< "4 3 1"

coins.pl:

#!/usr/bin/perl -pa
$_=!map{grep$`>=$_&&($n=$G[$`-$_]+1)<($G[$`]||=$n),@F,/$/}1..2*"@F"

@G1 से दो बार सबसे बड़े सिक्के के लिए कैशियर एल्गोरिथ्म द्वारा उपयोग किए गए सिक्कों की संख्या बनाता है । प्रत्येक राशि के लिए जाँच करता है कि अगर वह राशि 1 सिक्के के मूल्य से कम हो जाती है, तो कैशियर एल्गोरिदम को कम से कम 1 सिक्के की आवश्यकता होती है। यदि यह नहीं है तो एक प्रतिरूप (या पहले का प्रतिरूप था)। मैं पहले पलटवार पर रोक सकता था लेकिन यह अधिक बाइट्स लेता है। तो समय जटिलता है O(max_coin * coins)और अंतरिक्ष जटिलता हैO(max_coin)

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.