Acht Münzen für den schönen König


22

Dies ist ein "Gegenstück" zu einem anderen Puzzle, Acht Münzen für den fairen König bei Puzzling.SE.

Sie können das obige Puzzle für den Hintergrund lesen. Die Details zu diesem Puzzle sind wie folgt.

Ein Satz von 8 Arten von Münzen mit unterschiedlichen Werten wird erstellt. Der König möchte, dass Sie das maximale N herausfinden, sodass eine beliebige Anzahl von Preisen von 0 bis N mit einer Kombination von nicht mehr als 8 Münzen und ohne Gebühren bezahlt werden kann.

Zum Beispiel (entnommen aus Glorfindels Antwort). Wenn ein Satz Münzen mit den Werten 1, 2, 5, 13, 34, 89, 233, 610 angegeben wird, sollte Ihr Programm 1596 ausgeben, da jede Zahl zwischen 0 und 1596 (einschließlich) durch die Summe von nicht mehr dargestellt werden kann als 8 Nummern aus der angegebenen Liste (Nummern können sich wiederholen), während 1597 nicht auf diese Weise dargestellt werden kann.

In mathematischer Weise erfüllt, wenn die Eingabe eine Menge S ist, die aus 8 positiven ganzen Zahlen besteht, die gewünschte Ausgabe N, dass für jede Zahl n zwischen 0 und N x1, x2, x3, ..., x8 existiert, so dass

x1+x2+...+x8=nandx1,x2,...,x8{0}S

Ihr Ziel ist es, ein Programm, eine Funktion oder ein Snippet zu schreiben, das 8 Zahlen als Eingabe akzeptiert und das Maximum N wie oben beschrieben ausgibt.

Regeln:

  • Flexible I / O-Funktionen sind zulässig, sodass Ihr Programm die Eingaben in jeder am besten geeigneten Form verarbeiten kann. Sie können davon ausgehen, dass die eingegebenen Zahlen so sortiert sind, wie es für Ihr Programm am besten geeignet ist.
    • Bitte geben Sie dies in Ihrer Antwort an, wenn Ihr Programm von der Eingabereihenfolge abhängt
  • Die Eingabe besteht aus 8 verschiedenen positiven Ganzzahlen (keine Nullen). Die Ausgabe ist eine nicht negative Ganzzahl.
    • Falls der Eingabesatz keine 1 enthält, sollte Ihr Programm 0 ausgeben, da eine beliebige Zahl von 0 bis 0 die Anforderung erfüllt.
    • Im Falle einer ungültigen Eingabe (der Satz enthält null, negative oder doppelte Zahlen) kann Ihr Programm alles tun.
  • Standardlücken sind verboten.
  • Ihr Programm sollte innerhalb weniger Minuten auf einem modernen Computer ausgeführt werden.

Testfälle (meistens aus den Antworten unter der verknüpften Frage zu Puzzling entnommen):

[1, 2, 3, 4, 5, 6, 7, 8] => 64
[2, 3, 4, 5, 6, 7, 8, 9] => 0
[1, 3, 4, 5, 6, 7, 8, 9] => 72
[1, 2, 5, 13, 34, 89, 233, 610] => 1596
[1, 5, 16, 51, 130, 332, 471, 1082] => 2721
[1, 6, 20, 75, 175, 474, 756, 785] => 3356

Dies ist ein , also gewinnt das kürzeste Programm oder Snippet in jeder Sprache!


1
Nettes Puzzle, aber ich persönlich denke, dass einige weitere Testfälle hilfreich wären, um unsere Einsendungen zu testen.
Mr. Xcoder

Wäre es nicht besser, die Eingabegröße als Parameter festzulegen? Brute-Force-Ansätze kämpfen mit 8
Luis Mendo

1
@iBug Dann ist die übliche Regel so etwas wie "Einreichungen sollten in einer Minute in einem modernen Computer ausgeführt werden". Es ist unscharf, aber normalerweise gut genug, da der Unterschied zwischen Brute Force und effizienten Ansätzen sehr groß ist
Luis Mendo

1
Bei einem Zeitlimit von "ein paar Minuten" ist Brute Force weiterhin möglich. Eine leicht modifizierte Version meiner Antwort führt den letzten Testfall in 1m20s auf meinem 7 Jahre alten Laptop aus.
Nimi

1
@
Arnauld

Antworten:



9

Gelee , 12 Bytes

œċⱮ8Ẏ§ṢQJƑƤS

Probieren Sie es online!

Es dauert durchschnittlich ~ 3,7 Sekunden, um alle Testfälle auf TIO auf meinem Telefon auszuführen. Es ist also überraschenderweise ziemlich schnell.

Erläuterung

œċⱮ8Ẏ§ṢQJƑƤS     Monadic link / Full program.
  Ɱ8             Promote 8 to [1 ... 8] and for each value k:
œċ                    Generate all combinations of k elements from the list.
    Ẏ§           Tighten, then sum. Flatten to a 2D list then sum each.
      ṢQ         Sort the result and remove equal entries.
        JƑƤ      For each prefix of this list, return 1 if it is equal to its length range, 0 otherwise.
           S     Finally, sum the result (counts the 1's which is equivalent to what is being asked).

7

Haskell, 56 50 Bytes

g c=[x|x<-[1..],all((/=x).sum)$mapM(0:)$c<$c]!!0-1

Probieren Sie es online!

Ein Brute-Force-Ansatz. Fügen Sie 0der Liste der Münzen hinzu und probieren Sie alle Kombinationen von 8 Picks. Suchen Sie die erste Zahl n, die nicht der Summe der Picks entspricht, und kehren Sie zurück n-1.

Nimmt ungefähr 5m30s für [1, 2, 5, 13, 34, 89, 233, 610]meine 7-jährige Laptop-Hardware.

Edit: -6 Bytes dank @ Ørjan Johansen

Eine noch kürzere Version (-2 Bytes, nochmals dank @ Ørjan Johansen) ist

Haskell, 48 Bytes

g c=[x|x<-[1..],all((/=x).sum)$mapM(:0:c)c]!!0-1

Es verwendet jedoch erheblich mehr Speicher und führt zu starkem Paging auf meinem Computer und wird nicht "innerhalb weniger Minuten" beendet.


1
Sie können verwenden mapM(0:)$c<$c. (Eigentlich mapM(:0:c)csollte es funktionieren, aber für den gegebenen Testfall läuft die Zeit bei TIO aus.)
Ørjan Johansen

4

Gelee , 9 Bytes

Żœċ8§ḟ’$Ṃ

Probieren Sie es online!

Wie es funktioniert

Żœċ8§ḟ’$Ṃ  Main link. Argument: A (array)

Ż          Prepend a 0 to A.
 œċ8       Take all combinations of length 8, with repetitions.
    §      Take the sum of each combination.
       $   Combine the two links to the left into a monadic chain.
      ’      Decrement all sums.
     ḟ       Filterfalse; keep only sums that do not appear in the decremented sums.
        Ṃ  Take the minimum.

2
Żṗ8§ḟ’$Ṃspart ein Byte, aber ich bin nicht sicher, ob 8,5 Minuten als ein paar zählen .
Dennis


4

JavaScript (ES6),  100 88 80  76 Bytes

Dies ist im Wesentlichen eine Brute-Force-Suche, die jedoch durch Beschneiden verbessert wird, um sie zu beschleunigen. Die durchschnittliche Ausführungszeit für die Testfälle liegt bei TIO nahe 1 Sekunde.

Es wird davon ausgegangen, dass das Eingabearray vom höchsten zum niedrigsten sortiert ist.

a=>[...Array(a[0]*9)].findIndex(g=(i=8,s)=>s*i>0?a.every(x=>g(i-1,s-x)):s)-1

Probieren Sie es online!

Kommentiert

a =>                      // a[] = input array
  [...Array(a[0] * 9)]    // create an array of 9 * max(a) entries
  .findIndex(             // find the position of the first truthy result
    g = (i = 8, s) =>     // g = recursive function taking a counter i, initialized to 8
                          //     and a sum s, initialized to the position in the above array
      s * i > 0 ?         //   if s is positive and i is not equal to 0:
        a.every(x =>      //     for each value x in a[]:
          g(i - 1, s - x) //       do a recursive call with i - 1 and s - x
        )                 //     end of every()
      :                   //   else:
        s                 //     yield s (s = 0 means success and makes findIndex go on)
  ) - 1                   // end of findIndex(); decrement the result



2

Python 2 , 125 115 111 Bytes

lambda c:sum(i==j for i,j in enumerate(sorted(set(map(sum,product([0]+c,repeat=8))))))-1
from itertools import*

Probieren Sie es online!

Erwartet eine Liste von Ganzzahlen als Eingabe.

Erläuterung:

# an anonymous function
lambda c:
                                                          # get all length-8 combinations of values, from (0,0,0,0,0,0,0,0) to (8,8,8,8,8,8,8,8)
                                                          # zero is added to ensure that combinations of fewer than 8 coins are represented Ex:(1,0,0,0,0,0,0,0)
                                                          product([0]+c,repeat=8)
                                                  # for each combination, sum the values
                                                  map(sum,.......................)
                                       # get unique values, then sort them smallest to largest
                                       sorted(set(................................))
             # for each index, value pair, return if the index is equal to the value
             i==j for i,j in enumerate(.............................................)
         # in Python arithmetic, False is 0 and True is 1. So, count how many items match their index.
         # Since zero was added to the list, there will always be one extra match (0==0). So offset by one.
         sum(........................................................................)-1
from itertools import*

2

Perl6, 65 63 41 Bytes ( 39 37 Zeichen)

{@_=(0,|@_)X+(0,|@_)for ^3;($_ if $_==$++for @_.sort.unique)-1}

Probieren Sie es online!

Dies ist ein anonymer Block, der seine Daten als Array weitergibt. Das (0,|@_)ist ein schneller Weg , ein hinzufügen 0zu @_, und obwohl es zweimal getan, es ist immer noch ein bisschen kürzer als @_.push: 0;die dann Räume benötigen würde , nachdem die_ . Dies ist ein Brute-Force-Ansatz, der sich ein wenig auf die Tatsache stützt, dass es sich um 8 Kombinationen handelt. Nach dem Kreuzaddieren wird eine anonyme Liste für sequentielle Werte erstellt. Bei mathematischen Operatoren werden Listen nach ihrer Länge ausgewertet, sodass -1 die doppelte Pflicht hat: Berücksichtigung der 0 und Erzwingen von Int.

Dies kann seine süße Zeit in Anspruch nehmen, aber durch eine oder beiden Wechsel (0,|@_)zu (0,|@_.unique)vor dem ersten forkann es erheblich beschleunigt werden. Das erhöht die Punktzahl um +7 (Laufzeit <60s) oder +14 (Laufzeit <10s), wenn Sie der Meinung sind, dass die erste zu langsam ist (ich habe dies für den verknüpften Code getan, um Zeitüberschreitungen nach 60 Sekunden zu vermeiden).

Edit: JoKing in den Kommentaren verbessert es (gleiche Idee, Kreuz hinzufügen, dann das letzte aufeinanderfolgende Ergebnis zurückgeben) zu erstaunlichen 39 Zeichen (41 Bytes):

{(@_=@_ X+0,|@_)xx 3;first *+1@_,^∞}

Probieren Sie es online!

Die abschließende Tabellierung benötigt keine 0 und spart ein paar Bytes, indem nur einmal eine 0 hinzugefügt werden muss. Die xx 3imitiert die for-Schleife (noch Käse auf den Münzen ist eine Potenz von 2). Das firstSub gibt die erste Zahl in der unendlichen Liste zurück 0..*(dies ^Infist ebenfalls möglich, spart jedoch keinen Platz), die +1nicht Mitglied der Cross-Added-Liste ist. Wie bei mir ist es langsam, also addiere +7 für a uniquenach dem ersten Gleichgestellten, wenn du denkst, dass es für Richtlinien zu langsam ist.


1
48 Bytes . Technisch wird das uniquenicht benötigt, aber es beschleunigt es sehr
Jo King

@JoKing nett, ich weiß nicht, warum ich nicht über die Verwendung nachgedacht habe xx. Ich wusste, dass es eine Möglichkeit geben musste, die endgültige Tabellierung mit festgelegten Funktionen in viel kürzerer Zeit durchzuführen, aber mein Gehirn funktionierte nicht.
user0721090601

Das xx 1sollte seinxx 3
Jo King

@JoKing behoben. Ich erkannte auch zwei Zeichen (aber keine Bytes) kann durch die Verwendung gespeichert werden^∞
user0721090601

Tatsächlich können Sie mit ein paar Bytes sparen, (1...*∉@_)-1anstatt sie zu verwenden first(was genau die gleiche Methode ist, die ich hier verwendet habe )
Jo King

1

JavaScript (Node.js) , 171 145 115 Byte

f=(s,n=3)=>n?f(s=new Set(a=[0,...s]),n-1,a.map(m=>a.map(n=>s.add(m+n)))):Math.min(...[...s].filter(m=>!s.has(m+1)))

Probieren Sie es online! Port von @ Marks Python 3 Antwort. 108 Bytes in Firefox 30-57:

f=(s,n=3)=>n?f(new Set((for(n of s=[0,...s])for(m of s)n+m)),n-1):Math.min(...[...s].filter(m=>!s.has(m+1)))

1

Wolfram Language (Mathematica) , 46 Byte

0//.x_/;Min[Tr/@FrobeniusSolve[#,x+1]]<9:>x+1&

Probieren Sie es online!

Brute-Force-Ansatz: Prüft, ob ganze Zahlen aufwärts zählen, bis ein Wert erreicht ist, der mit 8 Münzen nicht bezahlt werden kann. Sehr, sehr langsam (tio times out), aber ich bin mir ziemlich sicher, dass der Zustand korrekt ist.


0

Sauber , 161 Bytes

import StdEnv,Data.List
$l=:[1:_]#k=sort(nub(map sum(iter 8(concatMap(\[h:t]=[[e,h:t]\\e<-[0:l]|e>=h]))[[0]])))
=length(takeWhile((>=)1)(zipWith(-)(tl k)k))
$_=0

Probieren Sie es online!

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.