Загрузка данных
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Random;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
class Sultan {
// =========================================================
// CAMPURI OBLIGATORII (cerute explicit de enuntul temei)
// =========================================================
private double bogatie; // bogatia sultanului (tip real)
private int numarSotii; // numarul de sotii (tip intreg) = populatia haremului
private double[] frumusete; // vector DINAMIC: frumusetea fiecarei sotii, 0-100
private double[] rautate; // vector DINAMIC: rautatea fiecarei sotii, 0-100
// campul STATIC: o singura copie, comuna tuturor obiectelor Sultan,
// care numara cate obiecte Sultan au fost create in total (in orice fel: prin oricare constructor)
public static int numarSultaniCreati = 0;
// =========================================================
// CONSTANTE (limite) - static final, cerute pentru validari
// =========================================================
static final double COEF_MIN = 0; // limita minima admisa pentru frumusete/rautate
static final double COEF_MAX = 100; // limita maxima admisa pentru frumusete/rautate
static final int MAX_SOTII = 20; // numar maxim de sotii acceptat (limita de siguranta)
// BufferedReader legat la tastatura (System.in), folosit pentru citire MANUALA,
// fara clasa Scanner - cerinta explicita a temei. E static: un singur obiect,
// partajat de toate metodele, in loc sa fie recreat la fiecare citire.
static BufferedReader tastatura = new BufferedReader(new InputStreamReader(System.in));
// =========================================================
// CONSTRUCTORI (3 tipuri cerute, toti cu alocare DINAMICA)
// =========================================================
/**
* 1) Constructor IMPLICIT (fara parametri).
* Seteaza valori "goale" / implicite: sultan fara nicio sotie.
* Vectorii sunt alocati cu dimensiune 0 (vectori valizi, dar fara elemente),
* consistent cu numarSotii = 0.
*/
Sultan() {
bogatie = 1000;
numarSotii = 0;
frumusete = new double[0]; // alocare dinamica, dimensiune 0
rautate = new double[0]; // alocare dinamica, dimensiune 0
numarSultaniCreati++; // inca un sultan a fost creat
}
/**
* 2) Constructor CU PARAMETRI.
* Primeste bogatia, numarul de sotii si valorile de frumusete/rautate
* care se aplica IDENTIC fiecarei sotii (pot fi modificate individual ulterior
* prin setFrumusete/setRautate).
*/
Sultan(double bogatie, int numarSotii, double frumusete, double rautate) {
this.bogatie = bogatie; // "this." e necesar: parametrul are acelasi nume ca si campul
this.numarSotii = numarSotii;
this.frumusete = new double[numarSotii]; // alocare dinamica, la dimensiunea primita
this.rautate = new double[numarSotii];
// umplem fiecare sotie cu aceleasi valori initiale primite ca parametru
for (int i = 0; i < numarSotii; i++) {
this.frumusete[i] = frumusete;
this.rautate[i] = rautate;
}
numarSultaniCreati++;
}
/**
* 3) Constructor DE COPIERE.
* Creeaza un obiect nou, independent, cu aceleasi valori ca "altul".
* IMPORTANT: .clone() e obligatoriu pe vectori - fara el, cele doua obiecte
* ar ajunge sa refere aceeasi zona de memorie, iar o modificare la unul
* s-ar reflecta (gresit) si asupra celuilalt.
*/
Sultan(Sultan altul) {
bogatie = altul.bogatie;
numarSotii = altul.numarSotii;
frumusete = altul.frumusete.clone(); // copie REALA a vectorului, nu doar a adresei
rautate = altul.rautate.clone();
numarSultaniCreati++;
}
// =========================================================
// METODE DE ACCES (get) - doar citesc, nu modifica nimic
// =========================================================
double getBogatie() { return bogatie; }
int getNumarSotii() { return numarSotii; }
// get cu validare de index: daca "i" nu e o pozitie valida, intoarcem -1
// (o valoare imposibila pentru frumusete reala, semnal ca ceva e gresit),
// in loc sa lasam programul sa arunce ArrayIndexOutOfBoundsException
double getFrumusete(int i) {
if (i >= 0 && i < numarSotii) {
return frumusete[i];
}
return -1; // index invalid -> valoare-semnal de eroare
}
double getRautate(int i) {
if (i >= 0 && i < numarSotii) {
return rautate[i];
}
return -1; // index invalid
}
// =========================================================
// METODE DE MODIFICARE (set) - valideaza INAINTE de a atribui
// =========================================================
// bogatia nu poate fi negativa
void setBogatie(double b) {
if (b >= 0) {
bogatie = b;
}
}
// numarul de sotii trebuie sa fie intre 0 si MAX_SOTII;
// la schimbarea numarului, REALOCAM ambii vectori la noua dimensiune
// (simplificare: nu pastram valorile vechi, pornim de la 0.0 pe fiecare pozitie noua)
void setNumarSotii(int n) {
if (n >= 0 && n <= MAX_SOTII) {
numarSotii = n;
frumusete = new double[n];
rautate = new double[n];
}
}
// set cu DUBLA validare: indexul trebuie sa fie valid SI valoarea trebuie
// sa fie in intervalul [COEF_MIN, COEF_MAX] = [0, 100]
void setFrumusete(int i, double v) {
if (i >= 0 && i < numarSotii && v >= COEF_MIN && v <= COEF_MAX) {
frumusete[i] = v;
}
}
void setRautate(int i, double v) {
if (i >= 0 && i < numarSotii && v >= COEF_MIN && v <= COEF_MAX) {
rautate[i] = v;
}
}
// =========================================================
// AFISARE - toate campurile obiectului
// =========================================================
// varianta scurta, foloseste un titlu generic
void printInfo() {
printInfo("Sultan");
}
// varianta cu ETICHETA (overloading - doua metode cu acelasi nume,
// parametri diferiti): utila cand afisam mai multi sultani la rand,
// ca sa stim exact care e care (ex: "s1 (implicit)", "harem[3]")
void printInfo(String eticheta) {
System.out.println("--- " + eticheta + " ---");
System.out.println("Bogatie: " + bogatie);
System.out.println("Numar sotii: " + numarSotii);
System.out.println(" # Frumusete Rautate");
for (int i = 0; i < numarSotii; i++) {
System.out.println(" " + i + " " + frumusete[i] + " " + rautate[i]);
}
System.out.println("Sanatate: " + coeficientSanatate());
System.out.println();
}
// =========================================================
// CITIRE DE LA TASTATURA - MANUAL, FARA Scanner
// (cerinta explicita a temei)
// =========================================================
// citeste o linie bruta de text de la tastatura;
// readLine() poate arunca IOException, de aceea e nevoie de try/catch
static String inString() {
String str = "";
try {
str = tastatura.readLine(); // AICI programul se opreste si asteapta Enter
} catch (IOException e) {
return str; // in caz de eroare de citire, intoarcem sir gol
}
return str;
}
// "traduce" textul citit intr-un numar intreg
static int inInt() {
return Integer.valueOf(inString()).intValue();
}
// "traduce" textul citit intr-un numar real
static double inDouble() {
return Double.valueOf(inString()).doubleValue();
}
// NOTA IMPORTANTA: aceasta metoda NU e apelata nicaieri in main()!
// Exista, functioneaza corect, dar main() ruleaza complet automat,
// fara sa astepte input de la tastatura (altfel programul s-ar bloca
// la rulare automata, asteptand un utilizator care nu exista).
// Pentru a o testa manual, trebuie apelata explicit: sultan.inputInfo();
void inputInfo() {
System.out.println("Bogatie:");
setBogatie(inDouble()); // citeste + valideaza prin setter
System.out.println("Numar sotii:");
setNumarSotii(inInt());
for (int i = 0; i < numarSotii; i++) {
System.out.println("Frumusete sotia " + i + ":");
setFrumusete(i, inDouble());
System.out.println("Rautate sotia " + i + ":");
setRautate(i, inDouble());
}
}
// =========================================================
// GENERARE DE VALORI ALEATOARE
// =========================================================
// suprascrie TOATE campurile obiectului cu valori aleatoare;
// util pentru a obtine rapid un sultan "plin" cu date plauzibile,
// fara sa le introduci manual de la tastatura
void randomize() {
Random r = new Random();
setBogatie(r.nextInt(1000000)); // bogatie: 0 - 999 999
setNumarSotii(1 + r.nextInt(5)); // 1 - 5 sotii (niciodata 0, ca sa aiba sens exemplul)
for (int i = 0; i < numarSotii; i++) {
// scriem direct in vector (nu prin setter): nextInt(101) da mereu 0-100,
// deci valoarea e deja garantat valida, validarea din setter ar fi redundanta
frumusete[i] = r.nextInt(101); // 0 - 100 inclusiv
rautate[i] = r.nextInt(101); // 0 - 100 inclusiv
}
}
// =========================================================
// COMPARARE STATICA dupa numarul de sotii
// =========================================================
// e STATIC pentru ca nu apartine unui singur sultan, ci compara doi
// sultani primiti ca parametri: se apeleaza Sultan.compareSotii(x, y)
static void compareSotii(Sultan a, Sultan b) {
if (a.numarSotii > b.numarSotii) {
System.out.println("Primul sultan are mai multe sotii (" + a.numarSotii + " > " + b.numarSotii + ")");
} else if (a.numarSotii < b.numarSotii) {
System.out.println("Al doilea sultan are mai multe sotii (" + b.numarSotii + " > " + a.numarSotii + ")");
} else {
System.out.println("Au acelasi numar de sotii (" + a.numarSotii + ")");
}
}
// =========================================================
// COEFICIENT DE SANATATE
// = direct proportional cu media frumusetii,
// invers proportional cu media rautatii sotiilor
// =========================================================
double coeficientSanatate() {
if (numarSotii == 0) return 0; // fara sotii nu are sens un calcul de medie (0/0)
double sumaFrumusete = 0, sumaRautate = 0;
for (int i = 0; i < numarSotii; i++) {
sumaFrumusete += frumusete[i];
sumaRautate += rautate[i];
}
double mediaFrumusete = sumaFrumusete / numarSotii;
double mediaRautate = sumaRautate / numarSotii;
if (mediaRautate == 0) mediaRautate = 1; // evitam impartirea la 0 (ar da Infinity)
return mediaFrumusete / mediaRautate; // relatia ceruta: frumusete / rautate
}
// =========================================================
// MAIN - demonstreaza tot ce s-a cerut in tema
// =========================================================
public static void main(String[] args) throws IOException {
// ---- PASUL 1: teanc de sultani, folosind toti cei 3 constructori ----
Sultan s1 = new Sultan(); // 1) implicit
Sultan s2 = new Sultan(50000, 3, 60, 30); // 2) cu parametri
s2.randomize(); // suprascriem s2 cu valori aleatoare
Sultan s3 = new Sultan(s2); // 3) copiere (dupa randomize!)
s1.printInfo("s1 (implicit)");
s2.printInfo("s2 (cu parametri + randomize)");
s3.printInfo("s3 (copie dupa s2)");
// ---- PASUL 2: vector dinamic de sultani, populat "pe bucati de 3" ----
// la fiecare grup de 3 pozitii: [implicit, cu parametri+randomize, copiere]
// -> demonstreaza ca toti cei 3 constructori pot popula acelasi vector
Sultan[] harem = new Sultan[6];
for (int i = 0; i < harem.length; i += 3) {
harem[i] = new Sultan();
harem[i + 1] = new Sultan(1000 * (i + 1), 2 + i % 3, 50, 50);
harem[i + 1].randomize();
harem[i + 2] = new Sultan(harem[i + 1]);
}
// ---- PASUL 3: afisam toti sultanii din vector, prin ciclu ----
System.out.println(">>> Vectorul harem <<<");
for (int i = 0; i < harem.length; i++) {
harem[i].printInfo("harem[" + i + "]");
}
// ---- PASUL 4: comparam cativa sultani dupa numarul de sotii ----
Sultan.compareSotii(s2, s3);
Sultan.compareSotii(harem[0], harem[1]);
// ---- PASUL 5: gasim cel mai sanatos sultan din vector ----
// tipar clasic de "gasire a maximului intr-un vector"
Sultan celMaiSanatos = harem[0];
for (int i = 1; i < harem.length; i++) {
if (harem[i].coeficientSanatate() > celMaiSanatos.coeficientSanatate()) {
celMaiSanatos = harem[i];
}
}
celMaiSanatos.printInfo("CEL MAI SANATOS SULTAN");
// ---- PASUL 6: suma TUTUROR sotiilor, folosind metodele de acces ----
// (cerinta explicita: "cu ajutorul metodelor de acces la campurile clasei")
int totalSotii = s1.getNumarSotii() + s2.getNumarSotii() + s3.getNumarSotii();
for (int i = 0; i < harem.length; i++) {
totalSotii += harem[i].getNumarSotii();
}
System.out.println("Total sotii (toti sultanii): " + totalSotii);
// ---- PASUL 7: numarul total de sultani creati (campul static) ----
System.out.println("Sultani creati: " + Sultan.numarSultaniCreati);
// ---- PASUL 8 (bonus, nota 10): salvam un sultan intr-un fisier text ----
s1.saveToFile("s1.txt");
}
// =========================================================
// SALVARE IN FISIER (cerinta pentru nota maxima)
// =========================================================
// scrie toate campurile obiectului intr-un fisier text, cate o valoare
// pe linie: bogatie, numarSotii, apoi perechi frumusete/rautate pentru
// fiecare sotie - acelasi format simplu, usor de citit ulterior
void saveToFile(String lab1jav) throws IOException {
BufferedWriter fisier = new BufferedWriter(
new FileWriter(lab1jav)
);
fisier.write(String.valueOf(bogatie));
fisier.newLine();
fisier.write(String.valueOf(numarSotii));
fisier.newLine();
for (int i = 0; i < numarSotii; i++) {
fisier.write(String.valueOf(frumusete[i]));
fisier.newLine();
fisier.write(String.valueOf(rautate[i]));
fisier.newLine();
}
fisier.close(); // obligatoriu: elibereaza fisierul si scrie efectiv pe disc
}
}