Skip to content

Commit

Permalink
Using binary search
Browse files Browse the repository at this point in the history
  • Loading branch information
mapio committed Nov 12, 2024
1 parent 8f7b701 commit 9a22a6a
Show file tree
Hide file tree
Showing 4 changed files with 163 additions and 44 deletions.
52 changes: 52 additions & 0 deletions src/main/java/it/unimi/di/prog2/h11/PolyClient.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*
Copyright 2024 Massimo Santini
This file is part of "Programmazione 2 @ UniMI" teaching material.
This is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This material is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this file. If not, see <https://www.gnu.org/licenses/>.
*/

package it.unimi.di.prog2.h11;

import java.util.Scanner;

/** A class to test some methods of {@link Poly}. */
public class PolyClient {

/** . */
private PolyClient() {}

/**
* Tests some methods of {@link Poly}.
*
* <p>Starting from term \( t_0 = 0 \) reads a list of \( t_i \) of terms from the standard input,
* given as a (coefficient, degree) pairs, and computes the polynomial \( t_0 + t_1 + t_2 \cdots
* \), emitting in the standard output the pairs "coefficient degree" for every term in the result
* (in increasing order of degree).
*
* @param args not used.
*/
public static void main(String[] args) {
Poly result = new Poly();
try (Scanner s = new Scanner(System.in)) {
while (s.hasNextInt()) {
Poly term = new Poly(s.nextInt(), s.nextInt());
result = result.add(term);
}
}
for (int d = 0; d <= result.degree(); d++) System.out.println(result.coeff(d) + " " + d);
}
}
102 changes: 58 additions & 44 deletions src/main/java/it/unimi/di/prog2/h11/SparsePoly.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@
package it.unimi.di.prog2.h11;

import it.unimi.di.prog2.h08.impl.NegativeExponentException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Objects;

Expand Down Expand Up @@ -51,33 +51,34 @@ public record Term(int coefficient, int degree) {
* RI:
*
* - degree >= 0
* - coefficient != 0
*
*/

/**
* Builds a term.
*
* @throws NegativeExponentException if {@code n} &lt; 0.
* @param coefficient the coefficient.
* @param degree the degree.
* @throws IllegalArgumentException if {@code n} &lt; 0 or {@code c} is 0.
*/
public Term { // using the compact constructor
if (degree < 0)
throw new NegativeExponentException("A term cannot have a negative exponent.");
public Term { // using the compact constructor, cannot declare throws
if (degree < 0) throw new IllegalArgumentException("A term cannot have a negative exponent.");
if (coefficient == 0)
throw new IllegalArgumentException("A term cannot have a zero coefficient.");
}
}

/** The array of terms (in increasing non-zero degree). */
/** The array of terms (in increasing degree). */
private final List<Term> terms;

/*-
* AF:
*
* AF(terms) = \sum terms[i]
*
* RI:
*
* - terms != null and does not contain nulls
* - terms is in strictly increasing degree order (i.e. there are no two terms with the same degree).
*
/*
* AF: associa a terms il polinomio dato dalla somma dei monomi in terms.
* RI: terms != null
* terms non deve contenere null
* terms non contiene due termini diversi col medesimo grado; detto
* altrimenti, 0 <= i < j < terms.size() allora
* terms.get(i).degree < terms.get(j).degree
*/

/** Initializes this to be the zero polynomial, that is \( p = 0 \). */
Expand All @@ -92,7 +93,7 @@ public SparsePoly() {
* @param n the degree.
* @throws NegativeExponentException if {@code n} &lt; 0.
*/
public SparsePoly(int c, int n) throws NegativeExponentException {
public SparsePoly(final int c, final int n) throws IllegalArgumentException {
terms = c == 0 ? Collections.emptyList() : List.of(new Term(c, n));
}

Expand All @@ -106,28 +107,16 @@ private SparsePoly(final List<Term> lst) {
terms = Collections.unmodifiableList(lst);
}

/**
* Finds the index of a term of given degree in a list of terms.
*
* @param lst the not {@code null} list of not {@code null} terms.
* @param d the degree.
* @return the index of a term of given degree, or -1 if none is present.
*/
private static int findByDegree(List<Term> lst, int d) {
for (int i = 0; i < lst.size(); i++) if (lst.get(i).degree == d) return i;
return -1;
}

/**
* Returns the coefficient of the term of given exponent.
*
* @param d the exponent of the term to consider.
* @return the coefficient of the considered term.
*/
public int coeff(int d) {
if (d < 0 || d > degree()) return 0;
int i = findByDegree(terms, d);
return i != -1 ? terms.get(i).coefficient : 0;
public int coeff(final int d) {
if (d > degree()) return 0;
final int i = findByDegree(terms, d);
return i >= 0 ? terms.get(i).coefficient : 0;
}

/**
Expand All @@ -140,6 +129,34 @@ public int degree() {
return terms.isEmpty() ? 0 : terms.get(terms.size() - 1).degree;
}

/**
* Finds the index (or insertion point) of a term of given degree in a list of terms in increasing
* degree order.
*
* <p>If the list contains a term of given degree, returns its index. Otherwise, returns {@code
* -(insertion_point) - 1} where {@code insertion_point} is the index of the first term with
* degree greater than {@code d}; note that this implies that the return value is non-negative iff
* the list contains a term of given degree.
*
* @see Collections#binarySearch(List, Object)
* @param lst the not {@code null} list of not {@code null} terms in increasing degree order.
* @param d the degree.
* @return the index of the term of given degree, or {@code -insertion_point - 1} if none is
* present.
*/
private static int findByDegree(final List<Term> lst, final int d) {
int lo = 0;
int hi = lst.size() - 1;
while (lo <= hi) {
int mid = lo + (hi - lo) / 2;
int midDegree = lst.get(mid).degree;
if (d < midDegree) hi = mid - 1;
else if (d > midDegree) lo = mid + 1;
else return mid;
}
return -lo - 1;
}

/**
* Adds a term to a list of terms in increasing degree order.
*
Expand All @@ -149,17 +166,14 @@ public int degree() {
* @param lst the not {@code null} list of not {@code null} terms in increasing degree order.
* @param term the not {@code null} term.
*/
private static void addTerm(List<Term> lst, Term term) {
private static void addTerm(final List<Term> lst, final Term term) {
if (term.coefficient == 0) return;
int i = findByDegree(lst, term.degree);
if (i != -1) {
int c = lst.get(i).coefficient + term.coefficient;
final int i = findByDegree(lst, term.degree);
if (i >= 0) {
final int c = lst.get(i).coefficient + term.coefficient;
if (c != 0) lst.set(i, new Term(c, term.degree));
else lst.remove(i);
} else {
for (i = 0; i < lst.size(); i++) if (lst.get(i).degree > term.degree) break;
lst.add(i, term);
}
} else lst.add(-i - 1, term);
}

/**
Expand All @@ -173,7 +187,7 @@ private static void addTerm(List<Term> lst, Term term) {
*/
public SparsePoly add(SparsePoly q) throws NullPointerException {
Objects.requireNonNull(q);
List<Term> result = new LinkedList<>(this.terms);
final List<Term> result = new ArrayList<>(this.terms);
for (Term t : q.terms) addTerm(result, t);
return new SparsePoly(result);
}
Expand All @@ -189,7 +203,7 @@ public SparsePoly add(SparsePoly q) throws NullPointerException {
*/
public SparsePoly mul(SparsePoly q) throws NullPointerException {
Objects.requireNonNull(q);
List<Term> lst = new LinkedList<>();
final List<Term> lst = new ArrayList<>();
for (Term tq : q.terms)
for (Term tt : terms)
addTerm(lst, new Term(tq.coefficient * tt.coefficient, tq.degree + tt.degree));
Expand Down Expand Up @@ -218,7 +232,7 @@ public SparsePoly sub(SparsePoly q) throws NullPointerException {
* @return this polynomial multiplied by \( -1 \).
*/
public SparsePoly minus() {
List<Term> lst = new LinkedList<>();
final List<Term> lst = new ArrayList<>();
for (Term t : terms) lst.add(new Term(-t.coefficient, t.degree));
return new SparsePoly(lst);
}
Expand Down
52 changes: 52 additions & 0 deletions src/main/java/it/unimi/di/prog2/h11/SparsePolyClient.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*
Copyright 2024 Massimo Santini
This file is part of "Programmazione 2 @ UniMI" teaching material.
This is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This material is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this file. If not, see <https://www.gnu.org/licenses/>.
*/

package it.unimi.di.prog2.h11;

import java.util.Scanner;

/** A class to test some methods of {@link SparsePoly}. */
public class SparsePolyClient {

/** . */
private SparsePolyClient() {}

/**
* Tests some methods of {@link SparsePoly}.
*
* <p>Starting from term \( t_0 = x + 1 \) reads a list of \( t_i \) of terms from the standard
* input, given as a (coefficient, degree) pairs, and computes the polynomials \( p_{i+1} = p_i
* \codt t_i + t_i \) emitting in the standard output the pairs "coefficient degree" for every
* term (in increasing order of degree) of the last computed polynomial.
*
* @param args not used.
*/
public static void main(String[] args) {
SparsePoly result = new SparsePoly(1, 1).add(new SparsePoly(-1, 0));
try (Scanner s = new Scanner(System.in)) {
while (s.hasNextInt()) {
SparsePoly term = new SparsePoly(s.nextInt(), s.nextInt());
result = result.mul(term).add(term);
}
}
for (int d = 0; d <= result.degree(); d++) System.out.println(result.coeff(d) + " " + d);
}
}
1 change: 1 addition & 0 deletions tests/it/unimi/di/prog2/h11

0 comments on commit 9a22a6a

Please sign in to comment.