Il problema delle monete


20

sfondo

La valuta ufficiale della nazione immaginaria del Golfenistan è il foo , e ci sono solo tre tipi di monete in circolazione: 3 foos, 7 foos e 8 foos. Si può vedere che non è possibile pagare determinati importi, come 4 soldi, usando queste monete. Tuttavia, possono essere formati tutti gli importi abbastanza grandi. Il tuo compito è quello di trovare la più grande quantità che non può essere formata con le monete (5 foos in questo caso), che è noto come il problema delle monete .

Ingresso

Il tuo input è un elenco di numeri interi positivi, che rappresentano i valori delle monete in circolazione. Due cose sono garantite al riguardo:L = [n1, n2, ..., nk]

  • Il GCD degli elementi di Lè 1.
  • L non contiene il numero 1.

Può essere non ordinato e / o contenere duplicati (pensa alle monete in edizione speciale).

Produzione

Poiché il GCD di Lè 1, ogni intero abbastanza grande mpuò essere espresso come una combinazione lineare non negativa dei suoi elementi; in altre parole, abbiamo

 m = a1*n1 + a2*n2 + ... + ak*nk 

per alcuni numeri interi . L'output è il numero intero più grande che non può essere espresso in questo modulo. Come suggerimento, è noto che l'output è sempre inferiore a , se e sono gli elementi massimi e minimi di ( riferimento ).ai ≥ 0(n1 - 1)*(nk - 1)n1nkL

Regole

È possibile scrivere un programma completo o una funzione. Vince il conteggio di byte più basso e non sono consentite scappatoie standard. Se la tua lingua ha un'operazione integrata per questo, non puoi usarla. Non ci sono requisiti di tempo o efficienza della memoria, tranne che dovresti essere in grado di valutare i casi di test prima di pubblicare la tua risposta.

Dopo aver pubblicato questa sfida, l'utente @vihan ha sottolineato che Stack Overflow ha un duplicato esatto . Sulla base di questa discussione Meta , questa sfida non verrà eliminata come duplicato; tuttavia, chiedo che tutte le risposte basate su quelle della versione SO debbano citare gli originali, ottenere lo status di Wiki della comunità ed essere eliminate se l'autore originale desidera pubblicare qui la propria risposta.

Casi test

[3, 7, 8] -> 5
[25, 10, 16] -> 79
[11, 12, 13, 14, 13, 14] -> 43
[101, 10] -> 899
[101, 10, 899] -> 889
[101, 10, 11] -> 89
[30, 105, 70, 42] -> 383
[2, 51, 6] -> 49

5
FrobeniusNumberin Mathematica.
alephalpha,

3
C'è un modo migliore per il limite superiore, trovato in questo documento che stabilisce (p - 1)(q - 1)come il limite superiore, dove pe qsono l'elemento più piccolo e più grande dell'insieme.
orlp,

2
Ci sono limiti di tempo di esecuzione o utilizzo della memoria?
Dennis,

1
Su Stack Overflow c'era una domanda di codice golf come questa qualche tempo fa
Downgoat,

1
Ho una soluzione Pyth da 13 byte che può fare [2,3]in un ragionevole lasso di tempo e nient'altro. [2,5]creerebbe circa un milione di liste Python in memoria.
isaacg

Risposte:


4

Pyth, 23 byte

ef!fqTs.b*NYQY^UTlQS*FQ

È molto lento, poiché controlla tutti i valori fino al prodotto di tutte le monete. Ecco una versione quasi identica, ma 1) riduce l'insieme di monete a quelle non divisibili tra loro e 2) controlla solo valori fino a (max(coins) - 1) * (min(coins) - 1)(47 byte):

=Qu?.A<LiHdG+GHGQYef!fqTs.b*NYQY^UTlQS*thSQteSQ

Spiegazione

                   S            range 1 to
                    *FQ         product of input
 f                             filter by
               UT                range 0 to T 
              ^  lQ              cartesian power by number of coins
   f                            filter by
      s.b*NYQY                   sum of coin values * amounts
    qT                           equals desired number T
  !                             nothing matching that filter
e                             take last (highest) element

8

Perl, 60 54 51 byte

50 byte di codice + 1 byte di riga di comando

$.*=$_,$r.=1x$_."|"}{$_=$.while(1x$.--)=~/^($r)+$/

Continuerà a giocare a golf e pubblicherà una spiegazione in seguito. L'approccio di base è lasciare che il motore regex faccia il duro lavoro con la corrispondenza delle stringhe. Ad esempio, costruirà una regex simile a^(.{3})*(.{7})*(.{8})*$ e corrisponderà a una stringa di lunghezza in ncui ndiscende dal prodotto degli input fino a quando non riesce a corrispondere.

Si noti che questo diventerà esponenzialmente lento all'aumentare del numero di argomenti.

Utilizzo: gli argomenti vengono letti da STDIN (nuova riga separata), ad esempio:

printf "101\n10" | perl -p entry.pl

3

R , 84 78 byte

Per un'iscrizione arbitraria di coprimes, un'1,un'2,..., L'importo di Frobenius è dato da

a=scan();max((1:(b<-min(a)*max(a)))[-colSums(combn(outer(a,0:b),sum(!!a)))])

Provalo online!

poiché è sempre più piccolo del prodotto dell'estremo un'io'S. Si tratta quindi di combinare tutte le possibili combinazioni (e altro) all'interno di tale intervallo. Grazie a Cole Beck per aver suggerito outersenza "*" e colSumspiuttosto che "apply (..., 2, sum)".

Una versione più veloce ma più lunga (di due byte) considera solo max(a):

a=scan();max((1:(min(a)*(b<-max(a))))[-apply(combn(outer(a,0:b,"*"),sum(!!a)),2,sum)])

Una versione leggermente più corta (78 bytes) che più spesso prende troppo il login o troppo spazio per funzionare su Provalo in rete è

a=scan();max((1:(b<-prod(a)))[-apply(combn(outer(a,0:b,"*"),sum(!!a)),2,sum)])

1

Python2, 188 187 byte

def g(L):
 M=max(L);i=r=0;s=[0]*M;l=[1]+s[1:]
 while 1:
    if any(all((l+l)[o:o+min(L)])for o in range(M)):return~-s[r]*M+r
    if any(l[(i-a)%M]for a in L):l[i]=1
    else:r=i
    s[i]+=1;i=(i+1)%M

Il secondo rientro viene visualizzato come 4 spazi su SO, quelli dovrebbero essere tab.

In realtà una soluzione "veloce", non bruta, utilizza il "Metodo di Wilf" come descritto qui .


1

Javascript ES6, 120 130 126 128 127 125 caratteri

f=a=>`${r=[1|a.sort((a,b)=>a-b)]}`.repeat(a[0]*a[a.length-1]).replace(/./g,(x,q)=>r[q]|a.map(x=>r[q+x]|=r[q])).lastIndexOf(0)

Versione alternativa 126 caratteri:

f=a=>{r=[1];a.sort((a,b)=>a-b);for(q=0;q<a[0]*a[a.length-1];++q)r[q]?a.map(x=>r[q+x]=1):r[q]=0;return r.join``.lastIndexOf(0)}

Test:

"[3, 7, 8] -> 5\n\
[25, 10, 16] -> 79\n\
[11, 12, 13, 14, 13, 14] -> 43\n\
[101, 10] -> 899\n\
[101, 10, 899] -> 889\n\
[101, 10, 11] -> 89\n\
[30, 105, 70, 42] -> 383\n\
[2, 51, 6] -> 49".replace(/(\[.*?\]) -> (\d+)/g, function (m, t, r) {
  return f(JSON.parse(t)) == r
})

1
Puoi sostituire il forEach(conmap(
Ypnypn il
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.