PDA

View Full Version : [c] aiuto algoritmo per neofita


fsdfdsddijsdfsdfo
06-12-2006, 19:14
Salve, sono un giovane studente di matematica alle prese con il C (avrò una 40ina di ore di laboratorio alle spalle, quindi pochissimo).


Vi spiego subito qual'è il mio obbiettivo.

Vorrei un programma che risolve un particolare gioco.

Quale gioco direte voi?
Consiste nel prendere una matrice 10*10. Mettere 1 nella prima casella v[0][0] e mettere la cifra successiva in una casella cosi scelta: o spostata di tre lungo le 4 direzioni cardinali, o spostata di due lungo le diagonali.
L'obbiettivo è, senza uscire mai dai bordi, riempire la matrice con 100 numeri.


Non ho la piu pallida idea di come fare.
Mi conviene indicizzare 100! matrici con tutte le combinazioni possibili? e poi verificare quali siano le matrici coerenti?

Oppure con una struttura ad albero provare tutte le combinazioni coerenti, andando avanti passo per passo e tornando indietro quando si arriva ad un assurdo?


Non ho nessuna idea su come implementare alcuno dei due modi.

Consigli?

Isomarcus
06-12-2006, 19:39
ma non ho capito, è il programma che decide dove mettere il numero successivo, oppure lui mette il primo numero e poi tu decidi in che direzione andare per piazzare il secondo?

fsdfdsddijsdfsdfo
06-12-2006, 19:45
ma non ho capito, è il programma che decide dove mettere il numero successivo, oppure lui mette il primo numero e poi tu decidi in che direzione andare per piazzare il secondo?
il programma deve trovare la soluzione al gioco.

Il primo numero è standard, cioè 1 in v[0][0] (uso la notazione C cosi è chiaro per tutti).

Partendo da qui, il programma deve trovare ALMENO un cammino (o forse tutti?) che riempa tutta la matrice fino a 100.

Capisci bene che non è banale trovare una soluzione, se prendete carta e penna vi accorgerete di quanto è difficile.

io personalmente in 6 mesi sono riuscito ad arrivare a 96.

Nota bene: Non voglio che mi scriviate il programma (anche se non mi darebbe fastidio :D:D) ma vorrei qualche indirizzo su come muovermi.

fsdfdsddijsdfsdfo
07-12-2006, 02:52
io ho provato a buttare giu un paio di righe di codice. Ma a quanto pare non funziona.

Ho inserito i commenti sui pezzi. Ho compilato con
gcc -Wall -pedantic -lm



provate a darci un occhiata. grazie :D:D

definizione: una matrice è coerente quando rispetta le regole del gioco.





#include <stdio.h>
#include <time.h>
#include <unistd.h>
#include <stdlib.h>
#include <math.h>


int main () {

int m[10][10], i, j, k, n, z, d;




for(;;) {

srand((unsigned)time(NULL));

for(i=0; i<100; i++) {
m[i/10][i%10]=rand()%100+1;
} //inizializzo una matrice con numeri casuali


m[0][0]=1;


for(n=100; n!=1; n--) {

for(k=100; k!=0 ; k--) {
if (m[k/10][k%10] == n) break;
}


for(z=100; z!=0 ; z--) {
if (m[z/10][z%10] == n-1) break;
}

d=sqrt( (z/10 - k/10)*(z/10 - k/10) + (z%10 - k%10)*(z%10 - k%10) );

// per ogni elemento cerco il suo elemento -1. Se la distanza tra
loro è due vuol dire che o è spostato di due sugli assi cardinali, o è spostato di
due sulla diagonale. In pratica verifico che la matrice sia coerente.
Tecnicamente siccome d è intero dovrebbe buttare la parte decimale della
radice no?

if (d!=2) break;

// esco dal ciclo for se la matrice non è coerente

}

if (n==1) break;

//se la matrice è coerente per tutti i numeri da 1 a 100 allora mi fermo
e stampo. A quanto pare non termina mai e va in loop, probabilmente la
matrice non potrà mai essere coerente secondo le regole da riga 25 a riga 40,
probabilmente perchè c'è qualche variabile con un uno di troppo (off-by-one).

}

for (i=0; i<10;i++) {
for(j=0; j<10; j++) {
if ( m[i][j] < 10) printf(" %d ", m[i][j]);
else printf("%d ", m[i][j]);
}
printf("\n");
}




return 0;
}

fsdfdsddijsdfsdfo
07-12-2006, 11:36
già non è per nulla banale :D:D:D:D


credo che il codice che ho scritto non sia sbagliato concettualmente, ma di sicuro ho alcuni problemi:


a) Come faccio a inizializzare casualmente una matrice con 100 numeri da 1 a 100 tutti DIVERSI tra loro?


b) come faccio a passare ad una funzione i RIFERIMENTI (cioè che modifico l'originale e non una copia) ad una matrice 10*10?

fsdfdsddijsdfsdfo
07-12-2006, 12:05
incredibile ma lol!

avevo sentito parlare del debugger... mi sono scaricato una guida e ho iniziato ad usarlo...
fighissimo!

gli ho fatto fare un paio di cicli...

sembra funzioni ma sia troppo lento :D:D

mi serve proprio qualcosa che mi dia 100 numeri DIVERSI! :D:D:

trallallero
07-12-2006, 12:47
mi serve proprio qualcosa che mi dia 100 numeri DIVERSI! :D:D:
per i numeri causali:

#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>

...
srand(getpid()); // INIZIALIZZA IL GENERATORE DI NUMERI

for ( y = 0; y < 100; y++ )
for ( x = 0; x < 100; x++ )
v[y][x] = rand();
...


EDIT: scusa non avevo capito ... tu vuoi 100 numeri casuali ma diversi ? :wtf:
quindi 100 numeri da 0 a 99 ma in ordine casuale ?

fsdfdsddijsdfsdfo
07-12-2006, 12:57
per i numeri causali:

#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>

...
srand(getpid()); // INIZIALIZZA IL GENERATORE DI NUMERI

for ( y = 0; y < 10; y++ )
for ( x = 0; x < 10; x++ )
v[y][x] = rand();
...


EDIT: scusa non avevo capito ... tu vuoi 100 numeri casuali ma diversi ? :wtf:
quindi 100 numeri da 0 a 99 ma in ordine casuale ?
esatto :D:D

solo non da 0 a 99 ma da 1 a 100. E che nella prima casella(m[0][0]) ci sia 1.

già che ci sei mi spieghi come passare un riferimento a matrice ad una funzione? grazie :D:D

andbin
07-12-2006, 13:04
a) Come faccio a inizializzare casualmente una matrice con 100 numeri da 1 a 100 tutti DIVERSI tra loro?Questo non sarebbe comunque un grosso problema, è abbastanza semplice, potrei pure postare del codice.

Piuttosto .... sei sicuro che sia la strada giusta??? Cioè tu generi la matrice in modo casuale e poi dopo verifichi se rispetta certe specifiche o condizioni, è così??

Personalmente vorrei capire meglio quali sono queste specifiche.

b) come faccio a passare ad una funzione i RIFERIMENTI (cioè che modifico l'originale e non una copia) ad una matrice 10*10?In "C" (e C++) un array viene passato ad una funzione sempre per riferimento (viene passato l'indirizzo del primo elemento).

trallallero
07-12-2006, 13:06
esatto :D:D

solo non da 0 a 99 ma da 1 a 100. E che nella prima casella(m[0][0]) ci sia 1.

già che ci sei mi spieghi come passare un riferimento a matrice ad una funzione? grazie :D:D
dammi un attimo di tempo che ho anche fare un lavoro (al lavoro si fa anche questo) :D

cionci
07-12-2006, 13:23
Io ti consiglierei di usare un algoritmo greedy: http://it.wikipedia.org/wiki/Algoritmo_greedy

trallallero
07-12-2006, 13:24
Allora, prova ad arrivarci da solo. Anzi magari ti viene un'idea migliore della mia :D

io farei un array intero di 100 inizializzato a 0.
Ottieni un numero causale, scorri l'array di 100, se il numero non c'é lo inserisci nell'array e lo aggiungi alla matrice altrimenti ottieni un altro random.
Non é molto performante ma é molto semplice ;)

andbin
07-12-2006, 13:30
Ecco come riempire una matrice 10x10 con numeri unici da 1 a 100 (in cui la cella [0,0] sia sempre 1):
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int rand_int (int min, int max)
{
double d;

d = rand () / (RAND_MAX+1.0);
return ((int) (d * (max-min+1))) + min;
}

void rand_matrice (int m[10][10])
{
int numeri[100], i, j, idx, n;

for (i = 0; i < 100; i++)
numeri[i] = i+1;

n = 99;

for (i = 0; i < 10; i++)
{
for (j = 0; j < 10; j++)
{
if (i == 0 && j == 0)
idx = 0;
else
idx = rand_int (0, n);

m[i][j] = numeri[idx];
numeri[idx] = numeri[n--];
}
}
}

void stampa_matrice (int m[10][10])
{
int i, j;

for (i = 0; i < 10; i++)
{
for (j = 0; j < 10; j++)
printf ("%3d ", m[i][j]);

printf ("\n");
}
}

int main (void)
{
int m[10][10];

srand ((unsigned int) time (NULL));

rand_matrice (m);

stampa_matrice (m);

return 0;
}

trallallero
07-12-2006, 13:32
già che ci sei mi spieghi come passare un riferimento a matrice ad una funzione? grazie :D:D
puoi fare una funzione del genere:
void Funz( int mat[10][10], int y, int x, int Val )
{
...
mat[y][x] = Val;
...
}

passi per riferimento ma specifichi anche le dimensioni della matrice

EDIT: scusa chiedevi come passare :rolleyes: (sono sempre piú stordito)
in questo caso passi semplicemente il nome:

int Mat[10][10];
...
Funz( Mat, 9, 9, 6 );

repne scasb
07-12-2006, 13:40
Mi conviene indicizzare 100! matrici con tutte le combinazioni possibili? e poi verificare quali siano le matrici coerenti?

Le matrici da analizzare secondo il tuo modello sono:

"933262154439441526816992388562667004907159682643816214685929638952175999932299\
156089414639761565182862536979208272237582511852109168640000000000000000000000\
00"

Oltretutto una volta generate, dovresti verificarle una per una fino a trovarne una che rispetti le condizioni del gioco....

Ziosilvio
07-12-2006, 13:42
prendere una matrice 10*10. Mettere 1 nella prima casella v[0][0] e mettere la cifra successiva in una casella cosi scelta: o spostata di due lungo le 4 direzioni cardinali, o spostata di uno lungo le diagonali.
L'obbiettivo è, senza uscire mai dai bordi, riempire la matrice con 100 numeri.
C'è qualcosa che non mi quadra.

Immagina la tua matrice come se fosse una scacchiera.
Se ti muovi di due unità in su, in giù, a destra, o a sinistra, passi da una casella a un'altra casella dello stesso colore.
Se ti muovi in diagonale, passi da una casella a un'altra casella dello stesso colore.

Allora, se ti muovi come dici tu, potrai riempire o tutte le caselle bianche, o tutte le caselle nere; ma non tutte le caselle, cosa che invece è chiesta dall'esercizio.

Dove sbaglio?

trallallero
07-12-2006, 13:56
vabbé, ti posto anche la mia versione. Non é ordinata in funzioni come quella di andbin ma almeno hai un paio di esempi ;)


int main()
{
int Mat[10][10];
int Vet[100];
int x, y, i, Count;

srand( getpid() );

memset( Mat, 0, sizeof(Mat) );
memset( Vet, 0, sizeof(Vet) );

// INIZIALIZZA LA MATRICE DA 10 x 10
for ( y = 0; y < 10; y++ )
for ( x = 0; x < 10; x++ )
{
while(1)
{
int R = rand() % 100 + 1;

for( i = 0; i < Count; i++ )
if ( Vet[i] == R )
break; // IL NUMERO C'E' GIA'

if ( Vet[i] == R )
continue; // RICOMINCIA IL while(1)

Mat[y][x] = Vet[Count++] = R;
break; // OK IL NUOVO NUMERO E' INSERITO
}
}

// STAMPA LA MATRICE
for ( y = 0; y < 10; y++, putchar('\n') )
for ( x = 0; x < 10; x++ )
printf( "%3i", Mat[y][x] );

return 0;
}

trallallero
07-12-2006, 13:57
C'è qualcosa che non mi quadra.

Immagina la tua matrice come se fosse una scacchiera.
Se ti muovi di due unità in su, in giù, a destra, o a sinistra, passi da una casella a un'altra casella dello stesso colore.
Se ti muovi in diagonale, passi da una casella a un'altra casella dello stesso colore.

Allora, se ti muovi come dici tu, potrai riempire o tutte le caselle bianche, o tutte le caselle nere; ma non tutte le caselle, cosa che invece è chiesta dall'esercizio.

Dove sbaglio?
mi sembra di averlo giá sentito questo gioco. Ti devi muovere ripettando le regole postate da dijo, é un solitario non ci sono caselle nere o bianche

Ziosilvio
07-12-2006, 14:25
mi sembra di averlo giá sentito questo gioco. Ti devi muovere ripettando le regole postate da dijo, é un solitario non ci sono caselle nere o bianche
Allora te lo dico in un altro modo.

Considera la somma delle coordinare della casella della matrice.

Se ti muovi di 2 in su o in giù, cambi di 2 il valore dell'ordinata e lasci intatto quello dell'ascissa; quindi, se la somma dell'ascissa e dell'ordinata era pari, rimane pari, e se era dispari, rimane dispari.
Se ti muovi di 2 a destra o a sinistra, cambi di 2 il valore dell'ascissa e lasci intatto quello dell'ordinata; quindi, se la somma dell'ascissa e dell'ordinata era pari, rimane pari, e se era dispari, rimane dispari.
Se ti muovi di 1 in diagonale, cambi di 1 sia l'ascissa che l'ordinata; quindi, se la somma dell'ascissa e dell'ordinata era pari, rimane pari, e se era dispari, rimane dispari.

Ma allora, muovendosi così, puoi andare solo sulle caselle in cui la somma dell'ascissa e dell'ordinata ha la stessa parità che in quella di partenza: e questo copre solo metà della matrice.

Di nuovo: dove sbaglio?

repne scasb
07-12-2006, 14:35
Allora te lo dico in un altro modo.

Considera la somma delle coordinare della casella della matrice.

Se ti muovi di 2 in su o in giù, cambi di 2 il valore dell'ordinata e lasci intatto quello dell'ascissa; quindi, se la somma dell'ascissa e dell'ordinata era pari, rimane pari, e se era dispari, rimane dispari.
Se ti muovi di 2 a destra o a sinistra, cambi di 2 il valore dell'ascissa e lasci intatto quello dell'ordinata; quindi, se la somma dell'ascissa e dell'ordinata era pari, rimane pari, e se era dispari, rimane dispari.
Se ti muovi di 1 in diagonale, cambi di 1 sia l'ascissa che l'ordinata; quindi, se la somma dell'ascissa e dell'ordinata era pari, rimane pari, e se era dispari, rimane dispari.

Ma allora, muovendosi così, puoi andare solo sulle caselle in cui la somma dell'ascissa e dell'ordinata ha la stessa parità che in quella di partenza: e questo copre solo metà della matrice.

Di nuovo: dove sbaglio?

Se parti dalla posizione (5,5), puoi andare in (5,8),(5,2),(2,5),(8,5) orizontale/verticale. (7,7),(7,3),(3,7),(3,3). Vai sia sugli ipotetiche caselle bianche che su quelle nere.

trallallero
07-12-2006, 14:36
Allora te lo dico in un altro modo.

Considera la somma delle coordinare della casella della matrice.

Se ti muovi di 2 in su o in giù, cambi di 2 il valore dell'ordinata e lasci intatto quello dell'ascissa; quindi, se la somma dell'ascissa e dell'ordinata era pari, rimane pari, e se era dispari, rimane dispari.
Se ti muovi di 2 a destra o a sinistra, cambi di 2 il valore dell'ascissa e lasci intatto quello dell'ordinata; quindi, se la somma dell'ascissa e dell'ordinata era pari, rimane pari, e se era dispari, rimane dispari.
Se ti muovi di 1 in diagonale, cambi di 1 sia l'ascissa che l'ordinata; quindi, se la somma dell'ascissa e dell'ordinata era pari, rimane pari, e se era dispari, rimane dispari.

Ma allora, muovendosi così, puoi andare solo sulle caselle in cui la somma dell'ascissa e dell'ordinata ha la stessa parità che in quella di partenza: e questo copre solo metà della matrice.

Di nuovo: dove sbaglio?
'azz! é vero! allora come ha fatto ad arrivare a 96 ? :wtf:
io personalmente in 6 mesi sono riuscito ad arrivare a 96.

trallallero
07-12-2006, 14:42
Se parti dalla posizione (5,5), puoi andare in (5,8),(5,2),(2,5),(8,5) orizontale/verticale. (7,7),(7,3),(3,7),(3,3). Vai sia sugli ipotetiche caselle bianche che su quelle nere.
infatti
ho chiesto ad un mio collega esperto di questi giochi:
ne salti 2 in orizzontale/verticale e ne salti 1 in diagonale.
Quindi ti muovi rispettivamente di 3 e 2 caselle.
Da come diceva dijo era 2 ed 1 caselle

fsdfdsddijsdfsdfo
07-12-2006, 15:04
sono contento il mio algoritmo abbia riscosso tanto successo :D:D


innanzitutto posto una soluzione:
http://www.vialattea.net/esperti/mat/gioco100/10x10numeri9.gif

fonte:

http://www.vialattea.net/esperti/php/risposta.php?num=2288

fsdfdsddijsdfsdfo
07-12-2006, 15:06
Io ti consiglierei di usare un algoritmo greedy: http://it.wikipedia.org/wiki/Algoritmo_greedy
sicuro possa funzionare?

dubito... e come scegliere qual'è la piu conveniente?

fsdfdsddijsdfsdfo
07-12-2006, 15:13
C'è qualcosa che non mi quadra.

Immagina la tua matrice come se fosse una scacchiera.
Se ti muovi di due unità in su, in giù, a destra, o a sinistra, passi da una casella a un'altra casella dello stesso colore.
Se ti muovi in diagonale, passi da una casella a un'altra casella dello stesso colore.

Allora, se ti muovi come dici tu, potrai riempire o tutte le caselle bianche, o tutte le caselle nere; ma non tutte le caselle, cosa che invece è chiesta dall'esercizio.

Dove sbaglio?

dalla casella (0.0) ti puoi muovere in diagonale a (2.2). Lasci una casella vuota e una la riempi.

fsdfdsddijsdfsdfo
07-12-2006, 15:13
infatti
ho chiesto ad un mio collega esperto di questi giochi:
ne salti 2 in orizzontale/verticale e ne salti 1 in diagonale.
Quindi ti muovi rispettivamente di 3 e 2 caselle.
Da come diceva dijo era 2 ed 1 caselle
si mi sono spiegato male :D:D:
non sono mai stato bravo con i conteggi :D:D

fsdfdsddijsdfsdfo
07-12-2006, 15:23
scusate...

il codice di andbin è semplicemente MERAVIGLIOSO :D:D

non capisco però cosa faccia questo (non ci sono riuscito neanche usando il debugger...



int rand_int (int min, int max)
{
double d;

d = rand () / (RAND_MAX+1.0);
return ((int) (d * (max-min+1))) + min;
}

beppegrillo
07-12-2006, 15:23
2 numeri consecutivi disposti diagonalmente distino 1 casella l'uno dall'altro.
Ovvero, casella intesa come?

Ziosilvio
07-12-2006, 15:24
Se parti dalla posizione (5,5), puoi andare in (5,8),(5,2),(2,5),(8,5) orizontale/verticale. (7,7),(7,3),(3,7),(3,3).
Quindi i movimenti orizzontali e verticali hanno lunghezza tre, non due; e quelli in diagonale hanno lunghezza due, non uno.
Per dijo: forse sarebbe il caso di sistemare il primo post...

fsdfdsddijsdfsdfo
07-12-2006, 15:27
Le matrici da analizzare secondo il tuo modello sono:

"933262154439441526816992388562667004907159682643816214685929638952175999932299\
156089414639761565182862536979208272237582511852109168640000000000000000000000\
00"

Oltretutto una volta generate, dovresti verificarle una per una fino a trovarne una che rispetti le condizioni del gioco....
a dir la verità sono un po meno :D:D:D

sono 99!

basta non prenderle tutte in una volta... ma solo una alla volta e verificarne la coerenza...


comunque questo è il mio algoritmo... l'ho fatto cosi solo perchè non sono in grado di farne uno meglio... nessuno ha qualche idea migliore?

andbin
07-12-2006, 15:28
non capisco però cosa faccia questo (non ci sono riuscito neanche usando il debugger...


int rand_int (int min, int max)
{
double d;

d = rand () / (RAND_MAX+1.0);
return ((int) (d * (max-min+1))) + min;
}
Innanzitutto per capirlo meglio dovresti leggere <qui> (http://www.hwupgrade.it/forum/showthread.php?t=1196677) l'ottima guida di ZioSilvio sulla generazione di numeri pseudocasuali.

Comunque nella funzione, 'd' può avere un valore da 0 (incluso) a 1.0 (escluso). Il calcolo nel return serve per avere il valore casuale intero con range da 'min' a 'max' inclusi.

fsdfdsddijsdfsdfo
07-12-2006, 15:29
2 numeri consecutivi disposti diagonalmente distino 1 casella l'uno dall'altro.
Ovvero, casella intesa come?
io la distanza non la misuro usando le coordinate ma contando le caselle bianche

fsdfdsddijsdfsdfo
07-12-2006, 15:32
Quindi i movimenti orizzontali e verticali hanno lunghezza tre, non due; e quelli in diagonale hanno lunghezza due, non uno.
Per dijo: forse sarebbe il caso di sistemare il primo post...
fatto :D:D

cionci
07-12-2006, 15:40
sicuro possa funzionare?

dubito... e come scegliere qual'è la piu conveniente?
Avevamo già affrontato una discussione simile, mi pare di avere anche postato una soluzione.
Il numero di celle libere raggiungibili deve guidare la scelta più conveniente: scegli al casella con il numero di celle libere minore...
Detto questo mi ricordo che non portava ad una soluzione per tutte le caselle di partenza, ma, a parità di numero di celle raggiungibili, bastava cambiare l'ordine di scelta e portava sempre ad una soluzione...

In caso di soluzione non raggiunta puoi anche memorizzare i passi fatti e fare un rollback scegliendo una strada diversa da quella che hai percorso...sempre utilizzando l'algoritmo greedy per la scelta...

repne scasb
07-12-2006, 15:40
a dir la verità sono un po meno[CUT]

La soluzione ottimale e' quella proposta dall'utente 'cionci'; in queste discussione http://www.hwupgrade.it/forum/showthread.php?t=559908 ti consiglio di seguire gli interventi dell'utente 'a2000'.

Per una soluzione piu' semplice esiste un "banale" modello esaustivo (allego sorgente in assembly x86 sviluppato molti anni orsono (per che e' interessato)):


.386
SEGMENT CODE USE16
ASSUME CS:CODE,DS:CODE
ORG 100h

TABLES EQU OFFSET DATA_START
DIRECTION_TABLE EQU TABLES + 100h
COUNTER_TABLE EQU DIRECTION_TABLE + 80h
SAVID PROC

mov ax,0FFFFh
mov di,TABLES
mov cx,50h
rep stosw
loop_start_point:
mov ax,ds: word ptr [i]
mov bx,ds: word ptr [j]
mov ds: word ptr [COUNTER_TABLE],ax
mov ds: word ptr [COUNTER_TABLE+2h],bx
shl bx,4h
add bx,ax
mov ds: byte ptr [bx+TABLES],bh
mov ds: byte ptr [DIRECTION_TABLE],bh
xor di,di
xor bp,bp
lea bp,[bp]
lea bp,[bp]
lea bp,[bp]
loop_counter:
mov bl,ds: byte ptr [di+DIRECTION_TABLE]
loop_direction:
mov si,di
shl si,2h
mov cx,ds: word ptr [si+COUNTER_TABLE]
mov dx,ds: word ptr [si+COUNTER_TABLE+2h]
jmp ds: word ptr [bx+direction_func]
func_0:
cmp cl,7h
jnb check_loop_direction
add cl,3h
jmp test_final_value
func_1:
cmp cl,8h
jnb check_loop_direction
cmp dl,8h
jnb check_loop_direction
add cl,2h
add dl,2h
jmp test_final_value
func_2:
cmp dl,7h
jnb check_loop_direction
add dl,3h
jmp test_final_value
func_3:
cmp cl,1h
jbe check_loop_direction
cmp dl,8h
jnb check_loop_direction
sub cl,2h
add dl,2h
jmp test_final_value
func_4:
cmp cl,2h
jbe check_loop_direction
sub cl,3h
jmp test_final_value
func_5:
cmp cl,1h
jbe check_loop_direction
cmp dl,1h
jbe check_loop_direction
sub cl,2h
sub dl,2h
jmp test_final_value
func_6:
cmp dl,2h
jbe check_loop_direction
sub dl,3h
jmp test_final_value
func_7:
cmp cl,8h
jnb check_loop_direction
cmp dl,1h
jbe check_loop_direction
add cl,2h
sub dl,2h
test_final_value:
mov si,dx
shl si,4h
add si,cx
cmp ds: byte ptr [si+TABLES],0FFh
jne check_loop_direction
inc di
add bl,2h
mov ax,di
mov ds: word ptr [di+DIRECTION_TABLE-1],bx
mov ds: byte ptr [si+TABLES],al
mov si,di
shl si,2h
mov ds: word ptr [si+COUNTER_TABLE],cx
mov ds: word ptr [si+COUNTER_TABLE+2h],dx
cmp bp,di
jb write_line
entry_line:
cmp di,63h
jne loop_counter
int 20h
ALIGN 10h
check_loop_direction:
add bl,2h
cmp bl,0Eh
jb loop_direction
func_8:
or di,di
je exit_loop_counter
mov si,di
shl si,2h
mov bx,ds: word ptr [si+COUNTER_TABLE+2h]
shl bx,4h
add bx,ds: word ptr [si+COUNTER_TABLE]
mov ds: byte ptr [bx+TABLES],0FFh
dec di
jmp loop_counter
exit_loop_counter:
inc ds: word ptr [i]
cmp ds: word ptr [i],0Ah
je loop_start_point
mov ds: word ptr [i],0h
inc ds: word ptr [j]
cmp ds: word ptr [j],0Ah
je loop_start_point
exit_prog:
ret
write_line:
mov si,OFFSET message_0+10h
lea ax,[di+1h]
call Write_Dec_Num
mov dx,OFFSET message_0
mov ah,9h
int 21h
pusha
xor dx,dx
loop_dx:
xor bx,bx
mov si,OFFSET message_1
mov di,8000h
mov cx,16h
rep movsw
loop_bx:
lea si,[bx+8002h]
mov di,bx
shr di,2h
mov ax,dx
shl ax,4h
add di,ax
movzx ax,ds: byte ptr [di+TABLES]
inc ax
cmp ax,256
jne writes
mov ds: dword ptr [si-2h],' XXX'
jmp no_writes
writes:
call Write_Dec_Num
no_writes:
add bx,4h
cmp bx,28h
jne loop_bx
pusha
mov dx,8000h
mov ah,9h
int 21h
popa
inc dx
cmp dl,0Ah
jne loop_dx
popa
mov bp,di
jmp entry_line

direction_func:
DW OFFSET func_0
DW OFFSET func_1
DW OFFSET func_2
DW OFFSET func_3
DW OFFSET func_4
DW OFFSET func_5
DW OFFSET func_6
DW OFFSET func_7
DW OFFSET func_8
i:
DW 0h
j:
DW 0h

message_0:
DB 'Soluzione con 000 elementi',0Dh,0Ah,'$'
message_1:
DB '000 000 000 000 000 000 000 000 000 000 ',0Dh,0Ah,'$'

Write_Dec_Num:
pusha
xor dx,dx
mov bx,0Ah
next_dec_num:
div bx
add dl,30h
mov ds: byte ptr [si],dl
xor dl,dl
dec si
or ax,ax
jne next_dec_num
popa
ret

ALIGN 10h
DATA_START:

SAVID ENDP
CODE ENDS
END SAVID