Xác định xem một hệ thống tiền xu là Canonical


48

Các của Thủ quỹ Thuật toán là một thuật toán cho việc thay đổi về số lượng tối thiểu của các đồng tiền mà làm việc khá tốt cho hầu hết các hệ thống tiền tệ. Tuy nhiên, giống như hầu hết các thuật toán tham lam, nó không phải là không có sai sót. Nếu một hệ thống tiền tệ được thiết lập vừa phải (hoặc chỉ sai), có một số giá trị nhất định trong đó Thuật toán của Thủ quỹ sẽ không tìm thấy thay đổi tối ưu.

Lấy ví dụ sau:

Chúng tôi có 4 xu, 3 và 1 ¢. Chúng tôi muốn thực hiện 6 ¢.

Thuật toán của Thủ quỹ trước tiên sẽ chọn nhiều đồng tiền lớn nhất (một 4 để bắt đầu) và trừ và lặp lại. Điều này sẽ dẫn đến một đồng 4 và hai đồng 1, với tổng số 3 đồng.

Thật không may cho Thuật toán có một cách để tạo ra 6 chỉ với hai đồng tiền (hai đồng tiền 3 ¢).

Một hệ thống thay đổi sẽ được coi là iff chính tắc cho tất cả các giá trị nguyên, Thuật toán của Thủ quỹ sẽ tìm thấy số lượng tiền tối ưu.

Bài tập, nhiệm vụ

Nhiệm vụ của bạn là lấy một hệ thống làm thùng chứa không có thứ tự hoặc thùng chứa số nguyên được sắp xếp đại diện cho các giá trị đồng xu và đưa ra một giá trị trung thực nếu đầu vào hệ thống là chính tắc và giả mạo.

Chương trình của bạn nên hoạt động cho tất cả các hệ thống có thể tạo ra bất kỳ giá trị nào. (tức là tất cả các hệ thống sẽ có 1 ¢ coin)

Đây là mã golf ít nhất thắng.

Các trường hợp thử nghiệm

Danh sách này không có nghĩa là toàn diện, chương trình của bạn sẽ hoạt động cho tất cả các đầu vào hợp lệ

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

@Geobits không phải trong mọi trường hợp, điều đó có nghĩa nhiều hơn là sự khác biệt tăng hoặc bằng từ đồng xu nhỏ nhất đến lớn nhất
Jörg Hülsermann

@ JörgHülsermann Điều đó cũng không thực sự đủ tốt. [1, 6, 13] có sự khác biệt ngày càng tăng, nhưng nó vẫn thất bại ở thứ gì đó như 18 (13 + 1 * 5 thay vì 6 * 3).
Geobits

16
Chúng được gọi là Hệ thống tiền Canonical . Bài viết ngắn này đưa ra thuật toán đa thức thời gian để kiểm tra xem một hệ thống tiền xu có hợp quy hay không (mặc dù một phương pháp kém hiệu quả hơn có thể là golfer). Một trường hợp thử nghiệm thú vị đang kiếm được 37 xu từ 25, 9, 4, 1(từ bài toán này. Bài đăng này ) - mặc dù mỗi đồng xu lớn hơn tổng của những đồng tiền nhỏ hơn, nhưng người không tham lam lại 25, 4, 4, 4đánh bại những kẻ tham lam 25, 9, 1, 1, 1.
xnor

1
@xnor Lưu ý rằng 9, 4, 1-> 4, 4, 4tốt hơn 9, 1, 1, 1là một ví dụ chặt chẽ hơn.
isaacg

Câu trả lời:


9

Haskell, 94 87 82 byte

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]

giải pháp này hoạt động bằng cách xác định một hàm jthực hiện thuật toán của nhân viên thu ngân và cho chúng tôi biết có bao nhiêu đồng tiền mà nhân viên thu ngân đã sử dụng. sau đó chúng tôi kiểm tra tới hai lần số lớn nhất trong danh sách, giả sử rằng hệ thống đã hợp quy cho tất cả các số trước đó, rằng lấy đồng tiền lớn nhất có thể là lựa chọn đúng đắn.

giải pháp này giả định đầu vào được sắp xếp.

bằng chứng kiểm tra lên đến hai lần số lớn nhất là đủ: giả sử rằng hệ thống không hợp quy cho một số nào đó ivà hãy klà số lớn nhất trong danh sách không lớn hơn i. giả sử rằng i >= 2kvà hệ thống là chuẩn cho tất cả các số nhỏ hơn i.

thực hiện một số cách tối ưu để kiếm ira tiền và giả sử nó không chứa tiền k. nếu chúng ta vứt đi một trong những đồng xu, thì số tiền mới phải lớn hơn kvà nhỏ hơn i- nhưng thuật toán của nhân viên thu ngân trên số này sẽ sử dụng kđồng xu - và do đó, bộ tiền này có thể được thay thế bằng một bộ tiền xu bằng nhau chứa đồng xu k, và do đó, có một tập hợp các đồng xu chứa đồng xu kcho số đó ivà bằng cách cảm ứng, thuật toán của nhân viên thu ngân trả về sự lựa chọn tối ưu.

lập luận này thực sự cho thấy rằng chúng ta chỉ cần kiểm tra cho đến khi tổng của hai yếu tố lớn nhất - nhưng sẽ dài hơn để làm như vậy.

Chỉnh sửa: giảm năm byte nhờ Ørjan Johansen!


1
Bạn có thể lưu một byte bằng cách sử dụng letthay vì where. Bạn có thể đặt nó làm |let ...bảo vệ mẫu sau f shoặc trong phạm vi hiểu danh sách.
Ørjan Johansen

1
Bốn byte khác với j i=last$0:[1+j(i-k)|k<-s,k<i].
Ørjan Johansen

5

Bình thường, 18 15 byte

!x#eST.gsky_S*e

Bộ kiểm tra

Một loại khác nhau của lực lượng vũ phu. Điều này bắt đầu bằng cách hình thành tất cả các bộ sưu tập tiền với tối đa k của mỗi đồng tiền, trong đó k là đồng tiền lớn nhất, được coi là đồng tiền cuối cùng. Tôi tin rằng điều này luôn đủ để tạo thành hai bộ tiền với cùng một số tiền, một tham lam và một ngắn hơn, bất cứ khi nào một cặp như vậy tồn tại.

Sau đó tôi xác định vị trí một cặp như sau:

Các tập hợp con được tạo theo thứ tự tăng kích thước và theo từ vựng theo vị trí trong đầu vào thứ hai. Nhóm các bộ sưu tập tiền theo tổng của họ, ổn định. Mỗi bộ sưu tập tiền được tạo theo thứ tự giảm dần, vì vậy giải pháp tham lam sẽ là yếu tố đầu tiên của nhóm nếu và chỉ khi giải pháp tham lam là tối ưu, và nó sẽ là yếu tố cuối cùng của nhóm theo từ vựng. Vì vậy, chúng tôi tìm thấy giải pháp tham lam và lọc theo chỉ số khác không trong nhóm. Nếu bộ đồng xu là đại bác, điều này sẽ lọc ra mọi thứ, vì vậy chúng tôi chỉ đơn giản phủ nhận một cách hợp lý kết quả và đầu ra.

Giải trình:

!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.

Rất hay - có ý kiến ​​nào giải thích tại sao nó bị treo trên herokuapp trong [1, 2, 4, 6, 8] và bị giết /opt/tryitonline/bin/pyth: line 5: 28070 Killed ... Exit code: 137tại TIO không? Chỉ cần hết bộ nhớ?
Jonathan Allan

Điều này sử dụng 2 ^ (num coins * đồng tiền cuối cùng) byte bộ nhớ. Vì vậy, ví dụ của bạn, 2 ^ 40. Không có nhiều máy có RAM terabyte
isaacg

Tôi nghĩ rằng đó có thể là trường hợp, mô tả của thuật toán có ý nghĩa, nhưng tôi đã không tính toán các con số - rất nhanh quá!
Jonathan Allan

5

PHP, 323 byte

Tương tự như cách khác đếm các đồng tiền cho đến khi tổng của hai phần tử cuối cùng trong mảng

<?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;

Câu trả lời dài nhất và dài nhất của tôi Tôi tin rằng> 370 Byte

Tôi chỉ cung cấp một phiên bản mở rộng vì nó dài hơn câu trả lời của tôi trước đó

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;

Giải thích cho câu trả lời này

Phiên bản trực tuyến

  1. Đặt tất cả trong mảng thành false == X

  2. Đặt tất cả các số trong mảng bạn điều khiển thành S

  3. Tìm thấy sự khác biệt giữa S cuối cùng và S khác hoặc 0

  4. Bắt đầu ở S cuối cùng trong mảng

  5. Đặt tất cả số thành D Trong đó S cuối cùng + một trong tất cả các khác biệt

  6. Bắt đầu từ tất cả D

  7. Đặt giá trị "T" thành D trong mảng

  8. GOTO 5 Lặp lại nó với tất cả các tìm thấy DI đã làm nó không thực sự trong mã

  9. Nếu mục tiếp theo trong Mảng có X thì đó là trường hợp sai khác Đúng

Các bước bổ sung Sự khác biệt là trong trường hợp trong đoạn 3 Giữa 1 và 4 là 2 X Điều này có nghĩa là bạn cần D thứ hai trước Bước 5. Sau giá trị này trong trường hợp này là 10 trường hợp đúng tôi có thể thấy cho đến nay có mối quan hệ giữa chênh lệch và số đếm trong mảng bạn kiểm soát để tính toán D (Bước 5) bạn cần lấy điểm trước khi bạn tìm thấy trường hợp sai cuối cùng.

Bạn đặt nhiều giá trị từ mục cuối cùng trực tiếp thành đúng. Những Điểm này có thể tạo ra sự khác biệt để quyết định xem có thể là số lượng đồng xu tham lam với giá trị tiếp theo là giống nhau sau đó là bội số của số cuối cùng trong mảng hay không. Mặt khác, bạn có thể thiết lập kẻ thù

  1. Đặt kẻ thù đầu tiên ở 1 + S cuối

  2. Từ điểm này, thêm từng giá trị trong mảng để đặt kẻ thù tiếp theo

  3. Bắt đầu với kẻ thù cuối cùng Goto 2

Nếu bây giờ bạn có kẻ thù và trường hợp thực sự trong đó thì xác suất tăng lên rằng số lượng có thể giống nhau Với nhiều D thì xác suất chìm xuống.

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>

thêm ? Byte Cảm ơn bạn @Jonathan ALLan đã cung cấp cho tôi các trường hợp kiểm tra sai
262 Byte Gần nhưng không đủ tốt 4 testcase sai trong thời điểm này

trường hợp thử nghiệm [1,16,256] trước nên đúng sau sai

<?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;

Thứ tự tăng dần của mảng

Giải trình

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

Có vẻ như những gì tôi đã thấy bảng chứa các giá trị từ [1,2,3,4,5,6] và tôi chỉ thay đổi mục cuối cùng cho đến 9. đối với 2to3 và 4to5, chúng tôi tạo giá trị của giá trị thấp hơn trong tính toán 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>


Tại sao bạn chia tay ", "khi bạn có thể tách ra ","; tại sao bạn chia khi bạn có thể lấy một danh sách; Tại sao bạn sắp xếp khi bạn có thể lấy một danh sách được sắp xếp? (Tôi cũng vẫn không chắc chắn nếu phương pháp mà bạn đang sử dụng là không thể sai lầm, có bạn một bằng chứng, bởi vì các tài liệu tôi đã đọc lướt qua dường như cho thấy nó là khó khăn hơn so với những gì tôi nghĩ mã của bạn đang làm.)
Jonathan Allan

@ JörgHülsermann Xin lỗi nếu tôi đã gây ra bất kỳ sự nhầm lẫn nào, mặc dù nó đã khác trước khi bạn có thể lấy danh sách đã sắp xếp nếu bạn chọn.
Thuật sĩ lúa mì

Tôi e rằng tôi nghĩ bạn sẽ phải kiểm tra nhiều hơn chỉ là mod 2 về sự khác biệt, như một ví dụ [1,2,5,11,17]là hợp quy. Có lẽ có một cái nhìn vào bài báo liên kết trong câu trả lời của tôi.
Jonathan Allan

... và chỉ để xác nhận nó với mã haskeller đáng tự hào chứ không phải của tôi: ideone.com/C022x0
Jonathan Allan

@WheatWizard là [1,2,5,11,17] đúng hay sai?
Jörg Hülsermann

4

JavaScript (ES6), 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")

Điều này cần mảng đầu vào được sắp xếp theo thứ tự giảm dần. Đối với mỗi giá trị từ 2N dowo 2 (N là giá trị đồng xu tối đa), nó tìm thấy số lượng tiền từ thuật toán tham lam và cố gắng tìm một bộ tiền xu nhỏ hơn.

Ít chơi gôn

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
}

Kiểm tra

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

Python, 218 211 205 byte

-1 byte nhờ @TuukkaX (một khoảng trắng có thể bị xóa giữa <3or)

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))

thay thế

Đầu vào theo thứ tự giảm dần.

Lực lượng vũ phu khủng khiếp. Bất kỳ tập hợp của một đơn vị tiền xu và một số đồng tiền khác là hợp quy. Đối với các bộ lớn hơn, trường hợp thất bại nhỏ nhất, nếu tồn tại sẽ lớn hơn hoặc bằng đồng xu nhỏ thứ 3 (không chắc bản thân nó có thể bằng như thế nào!) Và nhỏ hơn tổng của hai đồng tiền lớn nhất - hãy xem bài viết này (thực tế tham chiếu cái khác nhưng cũng đưa ra phương thức O (n ^ 3)).

g đếm các đồng tiền được sử dụng theo phương pháp tham lam và hàm không tên vượt qua các ứng cử viên có thể (thực tế từ 0 đến một ít hơn hai lần đồng xu lớn nhất để tiết kiệm byte) và tìm kiếm bất kỳ bộ sưu tập ít tiền nào cũng tính tổng số tiền đó.

ghoạt động bằng cách thực hiện những gì một nhân viên thu ngân sẽ làm, nó đệ quy lấy đồng tiền lớn nhất nhỏ hơn hoặc bằng số tiền vẫn còn để tạo ra, [v for v in c if v<=x][0]bỏ đi và đếm số lượng xu được sử dụng , n.

Hàm không tên trả về 1 nếu len(c)nhỏ hơn 3 và nếu không thì kiểm tra xem nó không phải là trường hợp, 1-...rằng bất kỳ giá trị nào trong phạm vi khả năng range(c[0]*2))), đều có thể với ít tiền hơn i in range(g(x,c)), bằng cách tạo ra một bộ sưu tập nhiều đồng tiền đó, c*ivà kiểm tra tất cả các kết hợp itiền xu combinations(c*i,i), để xem liệu có bất kỳ tổng nào có cùng giá trị không.


@WheatWizard, nó trả về Sai cho [13,8,2,1] - Tôi đã thêm nó vào các trường hợp thử nghiệm. Đã thêm làm rõ rằng đầu vào theo thứ tự giảm dần.
Jonathan Allan

1
3ornên làm việc.
Yytsi

Cảm ơn @TuukkaX, tôi cũng có thể thay thế not(...)bằng1-...
Jonathan Allan

2

Jelly ( ngã ba ), 15 14 byte

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

Giải pháp này sử dụng giới hạn cho các ví dụ phản tác dụng từ bài viết này . Ở đó, tác giả sử dụng một ràng buộc chặt chẽ cho ví dụ phản tác dụng, nhưng vì lợi ích của việc chơi golf, phạm vi của tổng số mệnh giá tiền xu được sử dụng lớn hơn và chứa ràng buộc đó.

Chương trình này tính toán tất cả các trường hợp thử nghiệm trong chưa đầy một giây trên máy của tôi.

Thật không may, điều này phụ thuộc vào một nhánh của Jelly nơi tôi đang thực hiện triển khai nguyên tử giải quyết Frobenius để bạn không thể thử trực tuyến.

Sử dụng

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

Hiệu suất là tốt và có thể giải quyết tất cả các trường hợp thử nghiệm cùng một lúc trong chưa đầy một giây.

$ 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

Giải trình

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

JavaScript (ES6), 144 132 124 122 110 byte

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)

Yêu cầu mảng được sắp xếp theo thứ tự giảm dần. Sử dụng quan sát trong bài báo được liên kết rằng nếu hệ thống không chính tắc thì có ít nhất một giá trị nhỏ hơn 2a [0] sẽ mất ít tiền hơn khi phân tách bằng cách sử dụng các đồng tiền không sử dụng từ thuật toán tham lam ban đầu.

Chỉnh sửa: Đã lưu 12 byte bằng cách nhận ra rằng tôi có thể kiểm tra tất cả các đồng tiền mặc dù tôi đã đạt được giá trị đích. Đã lưu 8 byte bằng cách chuyển đầu ra trung gian của tôi từ [l,b]sang [b,-l]; điều này cho phép tôi chuyển trực tiếp kết quả đầu tiên dưới dạng tham số của cuộc gọi thứ hai, cộng với một khoản tiết kiệm nhỏ phát hiện xem cuộc gọi thứ hai có thành công hay không. Đã lưu 2 byte bằng cách di chuyển định nghĩa gvào cuộc somegọi lại, cho phép tôi tránh việc chuyển không cần thiết trong biến vòng lặp hai lần. Đã lưu 12 byte bằng cách chuyển từ chức năng trình trợ giúp đệ quy của tôi sang một cuộc gọi đến filter(được thực hiện bởi công tắc đầu ra trung gian của tôi).


2

Perl, 69 byte

Bao gồm +2 cho -pa

Tặng tiền theo thứ tự giảm dần trên STDIN. Bạn có thể tùy ý bỏ 1tiền ra.

coins.pl <<< "4 3 1"

coins.pl:

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

Xây dựng số lượng đồng xu được sử dụng bởi thuật toán thu ngân @Gvới số tiền từ 1 đến hai lần số tiền lớn nhất. Đối với mỗi số tiền kiểm tra xem nếu số tiền đó giảm đi 1 giá trị thì thuật toán thu ngân cần tối đa 1 xu ít hơn. Nếu không đây là một ví dụ mẫu (hoặc đã có một mẫu phản ứng trước đó). Tôi có thể dừng lại ở ví dụ đầu tiên nhưng phải mất nhiều byte hơn. Vì vậy, độ phức tạp thời gian là O(max_coin * coins)và độ phức tạp không gian làO(max_coin)

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.