diff --git a/contents/IFS/IFS.md b/contents/IFS/IFS.md index 2ed1fe484..4b2531095 100644 --- a/contents/IFS/IFS.md +++ b/contents/IFS/IFS.md @@ -146,6 +146,8 @@ Here, instead of tracking children of children, we track a single individual tha [import:4-16, lang:"coconut"](code/coconut/IFS.coco) {% sample lang="java" %} [import:16-39, lang:"java"](code/java/IFS.java) +{% sample lang="rs" %} +[import:11-29, lang:"rust"](code/rust/IFS.rs) {% endmethod %} If we set the initial point to the on the equilateral triangle we saw before, we can see the Sierpinski triangle again after a few thousand iterations, as shown below: @@ -232,6 +234,8 @@ In addition, we have written the chaos game code to take in a set of points so t [import, lang:"coconut"](code/coconut/IFS.coco) {%sample lang="java" %} [import, lang:"java"](code/java/IFS.java) +{% sample lang="rs" %} +[import, lang:"rust"](code/rust/IFS.rs) {% endmethod %} ### Bibliography diff --git a/contents/IFS/code/rust/IFS.rs b/contents/IFS/code/rust/IFS.rs new file mode 100644 index 000000000..ad38aee87 --- /dev/null +++ b/contents/IFS/code/rust/IFS.rs @@ -0,0 +1,49 @@ +use std::fs::File; +use std::io::Write; + +// require create rand: +use rand::prelude::SliceRandom; +use rand::Rng; + +type Point = (f64, f64); + +// This function simulates a "chaos game" +fn chaos_game(n: u32, shape_points: Vec) -> Vec { + let mut rng = rand::thread_rng(); + + // initialize the output vector and the initial point + let mut output_points: Vec = Vec::new(); + let mut point = (rng.gen(), rng.gen()); + + for _ in 0..n { + output_points.push(point); + + let tmp = shape_points + .choose(&mut rng) + .expect("could not choose a shape point"); + + point = (0.5 * (point.0 + tmp.0), 0.5 * (point.1 + tmp.1)); + } + + output_points +} + +fn main() { + + // This will generate a Sierpinski triangle with a chaos game of n points for an + // initial triangle with three points on the vertices of an equilateral triangle: + // A = (0.0, 0.0) + // B = (0.5, sqrt(0.75)) + // C = (1.0, 0.0) + // It will output the file sierpinski.dat, which can be plotted after + + let shape_points = vec![(0.0, 0.0), (0.5, 0.75_f64.sqrt()), (1.0, 0.0)]; + + let output_points = chaos_game(10000, shape_points); + + let mut file = File::create("sierpinski.dat").expect("Unable to open/create the file"); + + for (x, y) in output_points { + writeln!(&mut file, "{}\t{}", x, y).expect("Unable to write to file"); + } +} diff --git a/contents/approximate_counting/approximate_counting.md b/contents/approximate_counting/approximate_counting.md index 654721844..aa678bd03 100644 --- a/contents/approximate_counting/approximate_counting.md +++ b/contents/approximate_counting/approximate_counting.md @@ -366,6 +366,8 @@ As we do not have any objects to count, we will instead simulate the counting wi [import, lang:"cpp"](code/c++/approximate_counting.cpp) {% sample lang="python" %} [import, lang:"python"](code/python/approximate_counting.py) +{% sample lang="java" %} +[import, lang:"java"](code/java/ApproximateCounting.java) {% endmethod %} ### Bibliography diff --git a/contents/approximate_counting/code/java/ApproximateCounting.java b/contents/approximate_counting/code/java/ApproximateCounting.java new file mode 100644 index 000000000..d59cbbf72 --- /dev/null +++ b/contents/approximate_counting/code/java/ApproximateCounting.java @@ -0,0 +1,82 @@ +import java.lang.Math; +import java.util.stream.DoubleStream; + +public class ApproximateCounting { + + /* + * This function taks + * - v: value in register + * - a: a scaling value for the logarithm based on Morris's paper + * It returns the approximate count + */ + static double n(double v, double a) { + return a * (Math.pow(1 + 1 / a, v) - 1); + } + + + /* + * This function takes + * - v: value in register + * - a: a scaling value for the logarithm based on Morris's paper + * It returns the new value for v + */ + static double increment(double v, double a) { + double delta = 1 / (n(v + 1, a) - n(v, a)); + + if (Math.random() <= delta) { + return v + 1; + } else { + return v; + } + } + + + + /* + * This function takes + * - v: value in register + * - a: a scaling value for the logarithm based on Morris's paper + * It returns the new value for v + */ + static double approximateCount(int nItems, double a) { + double v = 0; + + for (int i = 1; i < nItems + 1; i++) { + v = increment(v, a); + } + + return n(v, a); + } + + /* + * This function takes + * - nTrails: the number of counting trails + * - nItems: the number of items to count + * - a: a scaling value for th elogarithm based on Morris's paper + * - threshold: the maximum percent error allowed + * It terminates the program on failure + */ + static void testApproximateCount(int nTrails, int nItems, double a, double threshold) { + double avg = DoubleStream.generate(() -> approximateCount(nItems, a)) + .limit(nTrails) + .average() + .getAsDouble(); + + if (Math.abs((avg - nItems) / nItems) < threshold) { + System.out.println("passed"); + } + } + + + public static void main(String args[]) { + System.out.println("testing 1,000, a = 30, 1% error"); + testApproximateCount(100, 1_000, 30, 0.1); + + System.out.println("testing 12,345, a = 10, 1% error"); + testApproximateCount(100, 12_345, 10, 0.1); + + System.out.println("testing 222,222, a = 0.5, 10% error"); + testApproximateCount(100, 222_222, 0.5, 0.2); + } + +}