Programmare in java: 2. Tavola Pitagorica

Programmare in java: 2. Tavola Pitagorica

Risultato

    Il.
 


Link utili

▶ Esegui il programma su Replit:
1. Clicca sul link Apri su Replit per accedere al progetto.

2. Se non hai un account Replit, registrati gratuitamente oppure accedi con Google/GitHub.

3. Una volta nel progetto, premi “Run” per avviare l’esecuzione.

4. Puoi consultare il file sorgente e, se desideri, scaricarlo o copiarlo dal pannello di codice a sinistra.


▶ Scarica la versione portatile del codice:

1. Clicca sul link Scarica File per scaricare il file Tavola_pitagorica.txt, che contiene il codice sorgente completo in formato .txt.

2. Rinomina il file cambiando l’estensione da .txt a .java.

3. Ora puoi eseguirlo localmente su qualsiasi IDE per Java (es. VS Code, IntelliJ, NetBeans, Eclipse) oppure direttamente da terminale con i comandi javac e java, compilando e lanciando il file.


▶ Utilizzo:

L’ampiezza dell’intervallo n−n₀ è direttamente proporzionale alle dimensioni del display utilizzato per la visualizzazione: la scelta è lasciata alla discrezione dell’utente in base al proprio dispositivo.

replit.com
A

Tavola Pitagorica

@alessioseveri27


Codice

    Il.
 

Tavola Pitagorica Java
Tavola_pitagorica.java
1
2/*
3
4 Questo programma visualizza la tavola pitagorica per valori interi compresi tra due estremi n₀ e n scelti dall’utente.
5
6 Funzionalità principali:
7 – validazione dell'input (tipo, overflow e valore intero positivo, n > n₀, massimo 5 tentativi);
8 – evita l’overflow su n * n;
9 – scrittura della tavola pitagorica con intestazioni e griglia;
10 – gestione precisa e automatica del layout: calcolo dinamico della larghezza in base ai valori immessi;
11 – allineamento preciso e automatico dei numeri e simboli (intestazioni, separatori, angolo "x") in base ai valori immessi.
12
13 Convenzione matematica: ℕ = {1, 2, 3, …} (secondo Bourbaki).
14
15
16 Autore: Alessio Severi
17 Licenza: MIT License
18
19 MIT License
20
21 Copyright (c) 2025 Alessio Severi
22
23 Permission is hereby granted, free of charge, to any person obtaining a copy
24 of this software and associated documentation files (the "Software"), to deal
25 in the Software without restriction, including without limitation the rights
26 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
27 copies of the Software, and to permit persons to whom the Software is
28 furnished to do so, subject to the following conditions:
29
30 The above copyright notice and this permission notice shall be included in all
31 copies or substantial portions of the Software.
32
33 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
34 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
35 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
36 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
37 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
38 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
39 SOFTWARE.
40
41*/
42
43
44// File Tavola_pitagorica_v1.java
45
46
47import java.util.Scanner;
48
49public class Tavola_pitagorica {
50
51 public static void main(String[] args) {
52
53 // dichiarazione variabili nel main e inizzializzate ove necessario
54 int n, n0, count_cifra, x;
55 int flag= 1;
56 int flag1;
57 int[] count_flag = {0}; // array di supporto per contare i tentativi (passato per riferimento)
58
59
60 // creazione dell'oggetto, istanza della classe Scanner
61 Scanner sc= new Scanner(System.in); // warning: da convertire a try-with-resources (verrà trattato nelle lezioni successive)
62 // in tale programma la chiusura dello stream sottostante: System.in, viene gestita manualmente
63
64
65 // lettura convalidata dell'estremo inferiore n0
66 n0 = leggiInteroPositivo("\nInserisci l'estremo inferiore n0: ", sc, count_flag);
67
68
69 // controllo che il prodotto (n0+1) × (n0+1) non superi Integer.MAX_VALUE (evita overflow)
70 // poichè n>= n0+1
71 while ((long) (n0+1 ) * (n0+1) > Integer.MAX_VALUE) {
72
73 ++count_flag[0];
74
75 System.out.println("Attenzione: il valore di n0 deve essere un valore più piccolo.");
76
77 if(count_flag[0] == 5){
78
79 // avviso che sono finiti il numero massimo di tentativi per validare l'input
80 System.out.print("\n\n\nErrore: il numero massimo di tentativi per validare l'input sono finiti, input non validato.\n\n\n");
81
82 // chiusura dello stream sottostante: System.in, ossia libero la risorsa associata allo Scanner
83 sc.close();
84
85 return;
86 }
87 System.out.println(String.format("Hai ancora %d tentativi.", 5-count_flag[0]));
88 n0 = leggiInteroPositivo("Inserisci un nuovo valore per n (maggiore di n0): ", sc, count_flag);
89 }
90
91
92 // azzeramento dei tentativi prima del secondo input (sono distinti)
93 count_flag[0]= 0;
94
95 // lettura convalidata dell'estremo superiore n
96 n = leggiInteroPositivo("Inserisci l'estremo superiore n: ", sc, count_flag);
97
98
99 // controllo che n sia strettamente maggiore di n0 e che il prodotto n × n non superi Integer.MAX_VALUE (evita overflow)
100 while (n <= n0 || (long) n * n > Integer.MAX_VALUE) {
101
102 ++count_flag[0];
103 if(n <= n0) System.out.println("Attenzione: il secondo numero (n) deve essere maggiore del primo (n0).");
104 else System.out.println("Attenzione: il prodotto tra n e n deve essere un valore più piccolo.");
105
106 if(count_flag[0] == 5){
107
108 // avviso che sono finiti il numero massimo di tentativi per validare l'input
109 System.out.print("\n\n\nErrore: il numero massimo di tentativi per validare l'input sono finiti, input non validato.\n\n\n");
110
111 // chiusura dello stream sottostante: System.in, ossia libero la risorsa associata allo Scanner
112 sc.close();
113
114 return;
115 }
116 System.out.println(String.format("Hai ancora %d tentativi.", 5-count_flag[0]));
117 n = leggiInteroPositivo("Inserisci un nuovo valore per n (maggiore di n0): ", sc, count_flag);
118 }
119
120
121
122
123 System.out.println(String.format("\n\nTavola pitagorica da %d a %d\n\n", n0, n));
124
125 // calcolo del numero massimo di cifre per allineare correttamente i valori
126 count_cifra= (int)Math.log10(n*n) +1;
127
128
129 // stampa della tavola pitagorica con gestione dinamica per l'impaginazione di valori, intestazioni e separatori
130 for(int i=n0; i<=n; ++i){
131
132 // vengono effettuate copie della prima riga:
133 // la prima riga viene "duplicata" due volte, di cui una modificata per l'intestazione e una per i caratteri separatori
134 // i è l'indice di riga
135 if( i==n0+1 && flag<=2){
136 i= n0;
137 ++flag;
138 }
139
140 flag1= 1;
141
142 // vengono effettuate copie della prima colonna:
143 // la prima colonna viene "duplicata" due volte, di cui una modificata per l'intestazione e una per i caratteri separatori
144 // j è l'indice di colonna
145 for(int j=n0; j<=n; ++j){
146
147 if( j==n0+1 && flag1<=2){
148 j= n0;
149 ++flag1;
150 }
151
152 x=0;
153
154
155 // stampa angolo in alto a sinistra
156 if( flag== 1 && flag1 == 1){
157
158 System.out.print("x");
159 for(int l=1; l<= (int)Math.log10(i*j); ++l) System.out.print(" ");
160
161 }
162
163 // inizio della stampa di una parte della riga di separazione:
164 // al posto dei valori che verrebbero occupati in tale riga duplicata vengono inseriti "-" (step 1)
165 else if(flag== 2 ) for(int l=0; l<= (int)Math.log10(i*j); ++l) System.out.print("-");
166
167 // inizio della stampa di una parte della colonna di separazione:
168 // al posto dei valori che verrebbero occupati in tale colonna duplicata vine inserito "|" e
169 // aggiunti " " in modo da compensare la differenza di lunghezza tra un valore e il carattre "|"
170 else if(flag1== 2 ) {
171
172 System.out.print("|");
173 for(int l=1; l<= (int)Math.log10(i*j); ++l) System.out.print(" ");
174
175 }
176 // stampa dei valori della tavola
177 else if(flag== 1 || flag1== 1 ){
178
179 // stampa per l'intestazione della riga e della colonna rispettivamente;
180 if(flag== 1){
181 System.out.print(j);
182 for(int l=1; l<= (int)Math.log10(i*j)-(int)Math.log10(j); ++l) System.out.print(" ");
183 }
184 // if(flag1== 1)
185 else {
186 System.out.print(i);
187 for(int l=1; l<= (int)Math.log10(i*j)-(int)Math.log10(i); ++l) System.out.print(" ");
188 }
189
190 }
191 // stampa la tavola pitagorica
192 else System.out.print(i*j);
193
194
195 if(j== n){
196
197 // la riga di separazione finisce dove finisce il valore più grande contenuto nell'ultima colonna (step 3)
198 if(i==n0 && flag== 2 ) for(int l=1; l<= (int)Math.log10(n*n) – (int)Math.log10(i*j); ++l) System.out.print("-");
199
200 // vai a capo se raggiunta fine riga
201 System.out.print("\n");
202
203 }
204
205 // caloco dinamicamnte, in base ai valori che costituiscono la tavola pitagorica, gli spazi necessari affinchè
206 // si abbia un allineamento orizzontale dei valori in colonna, mentre nella riga di separazione con stessa logica
207 // verranno aggiunti "-" per continuarla (step 2).
208 else{
209
210 for(int k=0; k<=count_cifra-1; ++k) {
211
212 x= x+ (9* (int)Math.pow(10,k)); // restituisce un double Math.pow
213
214 if(i*j<= x && (i*j>= (int)Math.pow(10,k))) for(int l=1; l<= count_cifra – k; ++l) if(i==n0 && flag== 2 ) System.out.print("-");
215 else System.out.print(" ");
216
217 }
218 }
219 }
220 }
221
222 // migliora la leggibilità e l'esperienza utente
223 System.out.print("\n\n");
224
225 // chiusura dello stream sottostante: System.in, ossia libero la risorsa associata allo Scanner
226 sc.close();
227
228 }
229
230
231
232 // Metodo ausiliario: viene gestita la validazione dell'input:
233 // – controllo del tipo n (input non intero o overflow);
234 // – controllo del valore n (intero positivo);
235 public static int leggiInteroPositivo(String messaggio, Scanner sc, int[] count_flag) {
236
237 int valore;
238 int flag_error = 0;
239
240
241
242 // messaggio descrittivo per l'utente per l'immissione dell'input
243 System.out.print(messaggio);
244
245
246 // validazione dell'input n, scelto dall'utente
247 do{
248
249 // gestione della validazione errata e avvisi
250 while( (flag_error== 1) || (flag_error== 2)){
251
252 // messaggio all'utente, ps il codice Unicode per l'insieme dei numeri naturali è 2115, mentre 2208 è il codice Unicode per il simbolo di Peano.
253 // (java non supporta il LaTex)
254 System.out.println("\nAttenzione: input non valido, è necessario inserire un numero naturale n \u2208 \u2115 (convenzione di Bourbaki: \u2115 = {1, 2, 3 …}).");
255 System.out.println(String.format("Hai ancora %d tentativi.", 4-count_flag[0]));
256
257 // messaggio descrittivo per l'utente per l'immissione dell'input
258 System.out.print("Rinserisci un numero, intero positivo, n che sia valido: ");
259
260
261 // svuoto il buffer, se non ho un numero negativo o nullo, riempito dall'input, poiuchè il token viene validato.
262 // sc.nextLine(); restitituisce true se il buffer contiene almeno un token disponibile
263 if (flag_error== 1) sc.nextLine();
264
265
266 // conteggio dei tentativi falliti nella validazione dell'input
267 count_flag[0]++;
268
269 // controllo il numero di tentativi falliti (sono accettati max 5 tentativi)
270 if(count_flag[0] == 5){
271
272 // avviso che sono finiti il numero massimo di tentativi per validare l'input
273 System.out.print("\n\n\nErrore: il numero massimo di tentativi per validare l'input sono finiti, input non validato.\n\n\n");
274
275 // chiusura dello stream sottostante: System.in, ossia libero la risorsa associata allo Scanner
276 sc.close();
277
278 // il programma termina (con buffer svuotato)
279 System.exit(1);
280 }
281
282 flag_error= 0; // resetto il flag che segnala "errore sull'input" prima di rivalutare l'input
283
284 }
285
286 // controllo del tipo di input (parte 1)
287 if(!sc.hasNextInt()){
288 flag_error = 1; // errore 1: errore di tipo (l'input non è un numero intero: per esempio è una lettera, un carattere speciale, un emoji ecc…)
289 // oppure ho un overflow → fa eseguire il while
290
291 continue; // salta l'esecuzione di sc.nextInt(), poiché prima va svuotato il buffer
292 // → lo svuotamento verrà eseguito nel blocco while, che gestisce l'errore
293 }
294
295 // immissione dell'input dall'utente
296 valore= sc.nextInt();
297
298
299 // controllo del tipo di input (parte 2)
300 if (valore > 0) break; // input valido
301 else flag_error = 2; // errore 2: errore di valore (intero ≤ 0) → fa eseguire il while
302
303 }while (true);
304
305 // valore convalidato
306 return valore;
307 }
308
309}
310
311