[C]2 Esercizi semplici in C

C

computer7

Ospite
Salve posto di seguito 2 problemi da implementare in C , mi rendo conto che possono sembrare idioti, ma non riesco a implementarli.

1)Scrivere un programma che visualizzi, uno sotto l'altro, i seguentidisegni. Utilizzare dei cicli for per generare i disegni. Tutti gli asterischi dovranno essere
stampati da una singola istruzione printf.

(A)
*
**
***
*****
******
*******
********
*********
***********

**********
*********
********
*******
******
*****
****
***
**
*
E altri 2 triangoli specchiati...

2)
Un triangolo rettangolo può avere lati che siano tutti interi. L'insieme dei tre
valori interi per i lati di un triangolo rettangolo è detta terna pitagorica. Questi tre lati
devono soddisfare la relazione secondo cui la somma dei quadrati dei due cateti è uguale al
quadrato dell'ipotenusa. Inoltre se (a,b,c) è una terna pitagorica lo è anche (ka,kb,kc); se a e
b sono primi tra loro, allora la terna è detta primitiva, altrimenti è derivata.
Trovare tutte le terne pitagoriche del tipo (cateto1, cateto2, ipotenusa) che non siano
maggiori di 500. Scrivere una funzione che stabilisce se una terna di numeri interi è
pitagorica. Sviluppare un programma C che richiami la funzione suddetta e visualizzi tutte le
terne pitagoriche con un limite fissato dall'utente (ma non maggiore di 500). Usare dei cicli
(quali e quanti?) nidificati per provare tutte le possibilità.
 
Ultima modifica da un moderatore:
D

deleted_98961

Ospite
1) i triangoli specchiati li intendi in questo modo (l'allineamento non è mantenuto):
Codice:
*                                      *           
**                                  **
***                              ***
*****                       *****
******                   ******
*******                *******
********            ********
*********        *********
*********** ***********
con il triangolo sotto uguale.

2)
Allora il problema è un classico di ogni epoca, è una questione che viene discussa da secoli. Perciò la risoluzione può avvenire con più modi.

La definizione ci dice, che con a,b,c in N allora c^2 = a^2 + b^2

Il test se una data terna è pitagorica è semplicemente applicare la definizione, la scrittura di tal funzione è banale.

Calcolare tutte le terne pitagoriche per un limite fissato di 500 (che non si capisce molto a cosa si riferisca, cioè il limite desumo sia riferito al valore di c) è semplicemente l'utilizzo della funzione chiamola test_pit(a,b,c) che ad ogni combinazione di 3 elementi al variare di (a,b,c) ti stampa o memorizza la terna (controllando che c non superi il limite fissato dall'utente e il limite fissato dal testo).

Questo problema come è stato definito non è molto interessante (ne tantomeno efficiente).
Vedi se così ti è più chiaro il problema, il codice lo lascio a te, è presto scritto. :)


Un metodo più interessate per calcolare le terne pitagoriche è utilizzare la generalizzazione della definizone.

Siano m ed n interi positivi, ed m > n, allora:

a= m^2 - n^2
b= 2mn
c= m^2 + n^2

questa versione ci permette di trovare le terne pitagoriche primitive (come da testo del problema, ci sta apposta questa definizione :)), cioè quando MCD(a,b,c) = 1 (sono numeri primi). Le terne derivate si troveranno in un secondo momento, variano per un k in N perciò è subito calcolato conoscendo la terna primitiva.

Un metodo banale per applicare ciò è ciclare su m ed n e calcolare le terne (a,b,c) primitive, una volta fatto calcoliamo le terne derivate moltiplicando per ogni k fino al limite.
 
Ultima modifica da un moderatore:
C

computer7

Ospite
intanto grazie, cmq il problema delle terne pitagoriche a livello teorico l'ho capito ma nn riesco a implementarlo. Per il primo problema hai inteso giusto!:ok:
 
D

deleted_98961

Ospite
Per il primo problema hai inteso giusto!:ok:
dai un po' di fantasia... :)

Cosa ti sembrano gli asterischi? Non sembrano dei numeri in base 2?
Consideriamo:
- asterischi = 1
- spazi = 0
es.
Codice:
*                  *
1000001
...

Sia M la lunghezza della linea, allora il massimo numero in base due sarà 2^M - 1.
Il tutto si riduce a due iterazioni annidate, dove ci sarà una print * se ci sarà corrispondenza con il bit 1, print ' ' con bit 0. Che operatore bitwise permette questo?

Lascio a te concludere.


Per il 2) vedrò stasera di scriverti qualcosa per farti iniziare l'implementazione.


PS: chiedere di implementare il codice non serve a molto per imparare a scrivere in un linguaggio, ti posso dare una mano per iniziare, ma a svolgerlo devi essere te :)
 
C

computer7

Ospite
Guarda ho incominciato da poco a programmare in C e gli operatori bitwise non so cosa siano anche se vedendo qua e la in Internet ho incominciato a capire....( tanto per la cronaca conosco la porta XOR ma solo a livello elettronico, come porta logica per reti e so eseguire il complemento a 1 su carta...). Cmq faccio sempre gli esercizi che mi vengono proposti da solo, anke perche mi piace la "sfida", la risoluzione di problemi, perà non posso non ammettere che alle volte ho delle difficoltà:muro:. Quando diventerò piu esperto e consapevole dei miei mezzi userà sol farina del mio sacco! :). Cmq grazie del consiglio, saggio! :ok:
 
D

deleted_98961

Ospite
intanto grazie, cmq il problema delle terne pitagoriche a livello teorico l'ho capito ma nn riesco a implementarlo. Per il primo problema hai inteso giusto!
ok. Vediamo di scarnare il testo dell'esercizio e del problema per scrivere correttamente il codice.

Scrivere una funzione che stabilisce se una terna di numeri interi è pitagorica.
questo significa semplicemente applicare la definizione, perciò deve resituire true o false.

Codice:
boolean test_pit(a,b,c){

     if(c^2 == a^2 + b^2) return true;
     
     return false;

}


dalla forma generale si possono carpire diverse proprietà in alternativa del calcolo diretto. Per esempio:
se a e b sono uguali, non potrà mai esserci uguglianza con c ma solo maggiornaza. Perciò si può introdurre un if aggiuntivo:

Codice:
boolean test_pit2(a,b,c){

      if(a==b) return false;
      if(c^2 == a^2 + b^2) return true;

return false;

}



si potrebbero aggiungere altri if per evitare il calcolo diretto (visto che il codice si riutilizza a lungo andare diventa costoso), ma già con questo si tolgono alcuni casi inutili che apriori si sa non essere veri. Ma comunque l'esercio ci chiede solo di riutilizzare questa funzione nel calcolo di altre terne e non altro.


Sviluppare un programma C che richiami la funzione suddetta e visualizzi tutte le terne pitagoriche con un limite fissato dall'utente (ma non maggiore di 500). Usare dei cicli (quali e quanti?) nidificati per provare tutte le possibilità.

come detto questo è testare tutte le combinazioni (a meno di permutazioni di a e b) di 3 elementi.
Alcune considerazioni:
possiamo levare una parte considerevole di combinazioni notanto una ovvia proprietà, le terne valide sono quelle dove c > (a OR b) cioè non ci calcoliamo i valori di c minori di a e b. L'OR è messo perchè una terna valida è sia (a,b,c) che (b,a,c) cioè permutando i valori abbiamo un'altra terna, ma che non calcoliamo direttamente avendo già calcolata la prima (di solito non si considerano nemmeno queste terne, nel senso avendo una terna (3,4,5) è implicita (4,3,5), per capirci considerando (a,b) un vettore la norma è identica ma nello spazio hanno diversa disposizione). L'esercizio le chiede tutte, perciò le calcoliamo tutte.

Perciò, il codice terrà valide solo le terne dove:
c > b > a e le terne valide le permutiamo senza effettivamente calcolare le combinazione.

Perciò:
Codice:
int LIM_FIX = 500

c=3
while(c<=LIM_FIX){
    b=2 //si può inizializzare anche ad 1 ma non cambia.
    while(b<c){
        a=1
        while(a<b){

            if(test_pit(a,b,c)){
                print (a,b,c)

                print (b,a,c) //questo perchè
            }
        a++
        }
    b++
    }
c++
}

questo è tutto. Dovrebbe essere ok, devi controllare te (devi aggiungere il limite imposto dall'utente).
Dimmi cosa non ti è chiaro, che lo spiego volentieri :)


Cmq faccio sempre gli esercizi che mi vengono proposti da solo, anke perche mi piace la "sfida", la risoluzione di problemi, perà non posso non ammettere che alle volte ho delle difficoltà:muro:. Quando diventerò piu esperto e consapevole dei miei mezzi userà sol farina del mio sacco! :).
ma certo, tutti iniziano da qualche parte. Era solo una constatazione della tua richiesta. Questo genere di forum esiste apposta per aiutare un po' tutti ad ingranare negli esercizi pratici e nella teoria. :)

gli operatori bitwise non so cosa siano anche se vedendo qua e la in Internet ho incominciato a capire....( tanto per la cronaca conosco la porta XOR ma solo a livello elettronico, come porta logica per reti e so eseguire il complemento a 1 su carta...).
sono semplicemente gli operatori che lavorano a livello di bit. AND (&), OR (|), ... . In contrapposizione che gli operatori AND (&&), OR (||) che danno come risultato un valore booleano (true||false).
Il codice che avevo in mente è utilizzare l'operatore AND bit-a-bit che risulta 1 solo in corrispondenza di un asterisco.
Se ci calcoliamo precedentemente la forma che deve avere ogni linea, perchè è fissata la posizione degli asterischi possiamo sapere quando stampare uno spazio e quando no.

Es:
M=6
100001
110011
111111

ogni linea la consideriamo un numero binario (non mi addentro ma lo consideriamo con bit più significativo a sinistra) perciò:
100001 = 2^M-1 + 2^0
110011 = 2^M-1 + 2^M-2 + 2^1 + 2^0
111111 = 2^M-1 + 2^M-2 + 2^M-3 + 2^2 + 2^1 + 2^0

come vedi ci sono valori ripetuti, questo è a nostro vantaggio perchè lo trasformiamo nell'itarazione.
in forma generale:

t_i = 2^M-1-i + 2^i

Tornando all'operatore AND, per sapere QUANDO stampare un asterisco semplicemente confrontiamo il valore calcolato sopra con le potenze successivo di 2 perciò:
100001 AND 100000 (ricorda la posizione del bit più significativo) = 100000 che è un valore > 0 che per gli if vuol dire true
100001 AND 010000 = 000000 che è false perciò stampiamo uno spazio.

in definitiva:

Codice:
T=0
i=0
while(i<M/2){
    T= T + 2^(M-1)-i + 2^i //calcoliamo il valore della linea
    j=0
    while(j<M){
        if(T & 2^j) print *
        else print ' '
    j++
    }
i++
}

per il riflesso orizzontale basta modificare un attimo il codice (sostituisci M con una variabile che modificherai quando raggiungi la fine del primo triangolo). Se vorrai lo farai te, io mi fermo qui.
Ci sono ovviamente altre soluzioni ma questa mi pare più elegante per un esercizio del genere (in alternativa utilizza dei cicli annidati fermando le iterazioni a metà linea con degli if di controllo sugli spazi).
 
Ultima modifica da un moderatore:

Entra

oppure Accedi utilizzando
Discord Ufficiale Entra ora!