|
|||||||
|
|
|
![]() |
|
|
Strumenti |
|
|
#1 |
|
Senior Member
Iscritto dal: May 2004
Città: Londra (Torino)
Messaggi: 3692
|
[Vari] Contest 11: Change. NP-Hard.
Nella Repubblica di Kobolobo il ministro delle finanze e il direttore della banca centrale sono un po' burloni. Hanno deciso di ritirare tutto il contante dal paese, per far posto al nuovo conio, il kobolo.
Per stimolare la parte matematica dei Kobolobesi, hanno deciso di battere moneta nei seguenti tagli: Codice:
5 Koboli 9 Koboli 17 Koboli 30 Koboli 52 Koboli 111 Koboli 209 Koboli PROBLEMA 1: Quel e' il valore piu' alto che non e' possibile pagare utilizzando un qualsiasi quantitativo di monete tra quelle a disposizione? Esempi: 6 e 7 non si possono costruire, 14 e' possibile (9+5), 15 e' possibile (5+5+5), 16 non si riesce PROBLEMA 2: Sia dato in input un file avente il seguente formato: Codice:
C1 C2 C3 C4 ... Cn ------------------ T1 T2 T3 ... Tn E T1-Tn sono dei prezzi target. Domanda: Per ciascuno dei prezzi target, trovare una combinazione di monete che possa realizzarlo. In output e' richiesto un file. Per ciascun prezzo target Tx sara' necessario stampare una riga contenente il valore di ciascun pezzo trovato, separati da + Codice:
Esempio: 107 = 30+30+30+17 156 = 52+52+52 111 = 111 16 = N/A (quando non e' possibile realizzarlo) PROBLEMA 3: La cassiera del supermercato e' molto intelligente. Preferisce muovere il cervello piuttosto che muovere le mani. Ha pertanto deciso che ogni volta che dovra' consegnarci un resto, lo fara' utilizzando il minor numero di monete possibile. Avendo per esempio a disposizione monete di questo taglio: Codice:
1 10 100 105 sceglierebbe di darci 4 monete: 100+10+1+1 e non 8 monete: 105+1+1+1+1+1+1+1 Viceversa con un resto da 106 Koboli sceglierebbe 105+1 (2 monete) e non 100+5+1 (3 monete) Dato il file in input del problema 2, Per ciascuno dei prezzi target trovare il MINIMO NUMERO DI MONETE POSSIBILE e quali monete si devono utilizzare, producendo in output un file analogo a quello del problema 2 Quest'ultimo problema penso che sia un problema NP-Hard, la cui soluzione che non sia forza bruta non e' affatto semplice. Buon lavoro (e buona fortuna) e complimenti comunque a chiunque voglia avvicinarvisi.
__________________
Se pensi che il tuo codice sia troppo complesso da capire senza commenti, e' segno che molto probabilmente il tuo codice e' semplicemente mal scritto. E se pensi di avere bisogno di un nuovo commento, significa che ti manca almeno un test. Ultima modifica di gugoXX : 13-12-2008 alle 16:14. |
|
|
|
|
|
#2 |
|
Senior Member
Iscritto dal: May 2004
Città: Londra (Torino)
Messaggi: 3692
|
Di seguito il codice C# necessario per produrre il file di prova, per futuri utilizzi
Codice:
class Program
{
static void Main(string[] args)
{
Generator.Generate(@"C:\temp\C11F1.dat", 1000, 100000);
}
}
public static class Generator
{
private static Random rnd = new Random(1567654);
public static void Generate(string FileName, int nValori, int MaxValore)
{
StreamWriter sw = new StreamWriter(FileName);
int[] Coins = new int[] { 5, 9, 17, 30, 52, 111, 209, 500 };
Spool(sw, Coins);
sw.WriteLine("--------------");
Spool(sw, GetRNDList(nValori, MaxValore));
sw.Close();
}
private static IEnumerable<int> GetRNDList(int nValori, int MaxValore)
{
for (int u = 0; u < nValori; u++)
{
yield return rnd.Next(MaxValore);
}
}
private static void Spool(StreamWriter sw, IEnumerable<int> data)
{
data.ForAll(t => sw.WriteLine(t));
}
private static void ForAll<T>(this IEnumerable<T> domain, Action<T> act)
{
domain.ToList().ForEach(act);
}
}
__________________
Se pensi che il tuo codice sia troppo complesso da capire senza commenti, e' segno che molto probabilmente il tuo codice e' semplicemente mal scritto. E se pensi di avere bisogno di un nuovo commento, significa che ti manca almeno un test. |
|
|
|
|
|
#3 |
|
Senior Member
Iscritto dal: Nov 2006
Città: Mantova
Messaggi: 468
|
forse manca ->"di n cifre"?
|
|
|
|
|
|
#4 |
|
Senior Member
Iscritto dal: Feb 2006
Messaggi: 1304
|
Che significa NP e NP-hard?
Sono classificazione della difficoltà? EDIT: Boh intanto io ho fatto la versione brute force: Codice:
//noteValue contiene l'array dei valori dal piu' grande al piu' piccolo
void decompose( unsigned int targetSum )
{
std::cout << targetSum << " = ";
while( targetSum != 0 )
{
for( unsigned int i = 0; i < noteValuesNb; ++i)
{
if( targetSum >= noteValue[i])
{
targetSum -= noteValue[i];
std::cout << noteValue[i] << " ";
break;
}
}
}
}
Fra l'altro questo risolve anche il problema 2, dato che richiede UNA combinazione qualsiasi. EDIT2: Un metodo un pò meno brute force, ora va eseguito solo per ogni tipo di banconota. Su somme grosse è molto più veloce del precedente. Nel caso di numeri come 112 invece è meglio usare l'altro, credo. Io userei l'altro lo stesso, almeno si capisce senza lambiccarsi il cervello ![]() Codice:
unsigned int* decompose( unsigned int targetSum )
{
float valueCounted = 0;
unsigned int *times = (unsigned int*)malloc( sizeof( unsigned int ) );
for( unsigned int i = 0; i < noteValuesNb; ++i)
{
times[i] = (unsigned int)( ( targetSum - valueCounted ) / noteValue[i] );
valueCounted += times[i] * noteValue[i];
}
}
Ultima modifica di Tommo : 13-12-2008 alle 17:28. |
|
|
|
|
|
#5 |
|
Senior Member
Iscritto dal: Jun 2002
Città: Dublin
Messaggi: 5989
|
Cavoli, bel problema questo... Ci penserò mentre sono via e domani proverò a buttare giù qualche possibile soluzione.
__________________
C'ho certi cazzi Mafa' che manco tu che sei pratica li hai visti mai! |
|
|
|
|
|
#6 | |
|
Senior Member
Iscritto dal: May 2004
Città: Londra (Torino)
Messaggi: 3692
|
Quote:
Con complessita' ascendente abbiamo i P NP NP-hard NP-complete Ho idea che tu abbia scritto una soluzione greedy, che non e' detto funzioni ne per il punto 2 ne per il punto 3. Esempio, con i valori di moneta di test scritti all'inizio, se ti dicessero di comporre 156, quali valori otterresti con il tuo algoritmo?
__________________
Se pensi che il tuo codice sia troppo complesso da capire senza commenti, e' segno che molto probabilmente il tuo codice e' semplicemente mal scritto. E se pensi di avere bisogno di un nuovo commento, significa che ti manca almeno un test. Ultima modifica di gugoXX : 13-12-2008 alle 18:40. |
|
|
|
|
|
|
#7 |
|
Senior Member
Iscritto dal: Feb 2006
Messaggi: 1304
|
Boh a me pare corretta, almeno per il problema 3
Finchè la somma contiene la più grande, usa una di quelle, e così via... mi ci vuole un sacco a mettere su un coso di test, con lettura e scrittura... sei sicuro che non vada?
|
|
|
|
|
|
#8 | |
|
Senior Member
Iscritto dal: May 2004
Città: Londra (Torino)
Messaggi: 3692
|
Quote:
Immagina di avere come monete le seguenti: Codice:
5 Koboli 9 Koboli 17 Koboli 30 Koboli 52 Koboli 111 Koboli 209 Koboli Il tuo algoritmo prende 111 (che e' il piu' grande inferiore) quindi resta 156-111 = 45 Poi togli 30, resta 45-30 = 15 poi togli 9 resta 15-9 = 6 poi togli 5 resta 6-5 = 1, rimani li' Hai ottenuto 111+30+9+5, ovvero 4 monete, e non hai raggiunto il risultato. Un risultato per il punto 2 poteva essere p.es. 156 = 30+30+30+30+9+9+9+9 Mentre il risultato, ottimo, per il punto 3, doveva essere 156 = 52+52+52
__________________
Se pensi che il tuo codice sia troppo complesso da capire senza commenti, e' segno che molto probabilmente il tuo codice e' semplicemente mal scritto. E se pensi di avere bisogno di un nuovo commento, significa che ti manca almeno un test. |
|
|
|
|
|
|
#10 |
|
Senior Member
Iscritto dal: May 2004
Messaggi: 1136
|
|
|
|
|
|
|
#11 |
|
Senior Member
Iscritto dal: Apr 2000
Città: Vicino a Montecatini(Pistoia) Moto:Kawasaki Ninja ZX-9R Scudetti: 29
Messaggi: 53971
|
Con un algoritmo genetico sarebbe fattibile, è un po' un problema la ricombinazione
|
|
|
|
|
|
#12 |
|
Senior Member
Iscritto dal: May 2004
Messaggi: 1136
|
|
|
|
|
|
|
#13 |
|
Senior Member
Iscritto dal: Feb 2004
Messaggi: 1454
|
|
|
|
|
|
|
#14 |
|
Senior Member
Iscritto dal: Apr 2000
Città: Vicino a Montecatini(Pistoia) Moto:Kawasaki Ninja ZX-9R Scudetti: 29
Messaggi: 53971
|
|
|
|
|
|
|
#15 |
|
Senior Member
Iscritto dal: Nov 2005
Messaggi: 2787
|
E' un problema sullo stile di quello dello zaino vero? Non sono mai stato bravo in questo genere di problemi ma vorrei imparare a risolverli, appena ho del tempo mi cimento anche io
|
|
|
|
|
|
#16 |
|
Senior Member
Iscritto dal: Oct 2001
Messaggi: 11471
|
439 è la risposta giusta al primo quesito? Purtroppo mi è uscita una funzione ricorsiva e con numeri oltre le 5 cifre non ho abbastanza stack. Il codice è questo:
Codice:
def brute_force(money, i, coins)
return false if i == coins.size
i += 1 while (coins[i] > money) and (i+1 < coins.size)
money -= coins[i]
return false if money < 0
return true if money == 0
if not brute_force(money, i, coins)
brute_force(money+coins[i], i+1, coins)
else
return true
end
end
def remove_multiples_from_list(n, list)
n.step(list.size, n) do |i|
list[i] = nil
end
end
def contest_10(len, coins)
list = Array.new(('9'*len).to_i)
for i in 0..list.size
list[i] = i
end
for i in 1..coins.size
coins.combination(i).each do |c|
t = c.inject {|tot, x| tot += x}
remove_multiples_from_list(t, list)
end
end
list.compact!
i = list.size - 1
i -= 1 while brute_force(list[i], 0, coins)
list[i]
end
coins = [209, 111, 52, 30, 17, 9, 5]
puts contest_10(5, coins)
Ultima modifica di VICIUS : 15-12-2008 alle 07:47. Motivo: Mancava un +coins[i] |
|
|
|
|
|
#17 |
|
Senior Member
Iscritto dal: May 2004
Città: Londra (Torino)
Messaggi: 3692
|
Mi sa di no.
439 = 9+ 5*86 Comunque quel cabasiso di Vincenzo ha trovato in una biblioteca segreta la soluzione al quesito 3 (e quindi anche al 2) e l'ha realizzata come sempre in C. Mi piacerebbe vedere soluzioni Naive, che possano dare i risultati corretti anche se non per forza realizzati con un algoritmo ottimo (PS: Essendo NP-Hard non e' dimostrabile che un algoritmo, sebbene dia i risultati corretti, sia quello ottimo). Diciamo soluzioni "nuove", non realizzate con algoritmi noti. P.es. il tuo approccio Vicius mi piace.
__________________
Se pensi che il tuo codice sia troppo complesso da capire senza commenti, e' segno che molto probabilmente il tuo codice e' semplicemente mal scritto. E se pensi di avere bisogno di un nuovo commento, significa che ti manca almeno un test. Ultima modifica di gugoXX : 14-12-2008 alle 23:47. |
|
|
|
|
|
#18 | ||
|
Senior Member
Iscritto dal: May 2004
Città: Londra (Torino)
Messaggi: 3692
|
In Behalf of Vincenzo
Quote:
__________________
Se pensi che il tuo codice sia troppo complesso da capire senza commenti, e' segno che molto probabilmente il tuo codice e' semplicemente mal scritto. E se pensi di avere bisogno di un nuovo commento, significa che ti manca almeno un test. |
||
|
|
|
|
|
#19 | |
|
Senior Member
Iscritto dal: Dec 2005
Città: Istanbul
Messaggi: 1817
|
Quote:
__________________
One of the conclusions that we reached was that the "object" need not be a primitive notion in a programming language; one can build objects and their behaviour from little more than assignable value cells and good old lambda expressions. —Guy Steele |
|
|
|
|
|
|
#20 | |
|
Senior Member
Iscritto dal: May 2004
Città: Londra (Torino)
Messaggi: 3692
|
Quote:
Ma poiche' penso (pensavo) che non tutti conoscessero la programmazione dinamica, e soprattutto come riuscire a costruire un nuovo algoritmo dinamico dato uno specifico problema, speravo che potesse venire fuori qualcosa di interessante.
__________________
Se pensi che il tuo codice sia troppo complesso da capire senza commenti, e' segno che molto probabilmente il tuo codice e' semplicemente mal scritto. E se pensi di avere bisogno di un nuovo commento, significa che ti manca almeno un test. |
|
|
|
|
|
| Strumenti | |
|
|
Tutti gli orari sono GMT +1. Ora sono le: 02:16.






















