From 4b05d4379efa967f141627cc7db57402ea09f373 Mon Sep 17 00:00:00 2001 From: Gregor Kleen Date: Fri, 20 Nov 2015 18:15:57 +0100 Subject: EiP - H5-1 --- ws2015/eip/blaetter/05/Histogramm.java | 111 +++++++++++++++++++++++++++++++++ ws2015/eip/blaetter/05/manifest | 1 + 2 files changed, 112 insertions(+) create mode 100644 ws2015/eip/blaetter/05/Histogramm.java (limited to 'ws2015') diff --git a/ws2015/eip/blaetter/05/Histogramm.java b/ws2015/eip/blaetter/05/Histogramm.java new file mode 100644 index 0000000..87e6b4e --- /dev/null +++ b/ws2015/eip/blaetter/05/Histogramm.java @@ -0,0 +1,111 @@ +import java.awt.Rectangle; +import java.awt.Color; +import java.awt.Point; + +class Histogramm { + + public static final int SPACING = 1; + public static final int MIN_BAR_WIDTH = 2; + public static final int HEIGHT = 480; + public static final int LABEL_HEIGHT = 12; + public static final int MIN_WIDTH = 640; + + public static final Color COLD = Color.blue; + public static final Color HOT = Color.red; + + public static void main(String[] args) + { + if (args.length < 2) + { + System.err.println("Need at least two arguments"); + System.exit(2); + } + + String input = ""; + for (int i = 1; i < args.length; i++) + input += args[i]; + + char[] alphabet = args[0].toCharArray(); + // We convert to char[] instead of byte[] in order to be unicode aware + + graph(alphabet, makeRelative(countOccurences(alphabet, input))); + // Why can’t we have nice things? Like function composition? + } + + public static double[] makeRelative (int[] counts) + { + double[] relativeCounts = new double[counts.length]; + int max = 0; + + // I'm sure there's a library function for this but I was too lazy to look + for (int c : counts) + if (c > max) + max = c; + + for (int i = 0; i < counts.length; i++) + relativeCounts[i] = ((double) counts[i]) / max; + + return relativeCounts; + } + + public static void graph(char[] alphabet, double[] counts) + { + int minWidth = MIN_BAR_WIDTH * (counts.length) + SPACING * (counts.length - 1); + int width = Math.max(minWidth, MIN_WIDTH); + + int barWidth = (width - SPACING * (counts.length - 1)) / counts.length; + + GraphicsWindow gw = new GraphicsWindow(width, HEIGHT); + gw.setText("Histogramm"); + + int x = 0; + + for (int i = 0; i < counts.length; i++) + { + int height = (int) (counts[i] * HEIGHT); + Point corner = new Point(x, HEIGHT - height); + Rectangle bar = new Rectangle(corner.x, corner.y, barWidth, height); + boolean labelAbove = height <= LABEL_HEIGHT; + + + gw.setColor(color(counts[i])); + gw.fill(bar); + gw.setColor(labelAbove ? Color.black : Color.white); + gw.drawStringAt(String.format("%c", alphabet[i]), new Point(corner.x, corner.y + (labelAbove ? -5 : LABEL_HEIGHT))); + + x += SPACING + barWidth; + } + + gw.mouseClick(); + System.exit(0); + } + + public static Color color(double c) + { + double r, g, b; + r = HOT.getRed() * c + COLD.getRed() * (1 - c); + g = HOT.getGreen() * c + COLD.getGreen() * (1 - c); + b = HOT.getBlue() * c + COLD.getBlue() * (1 - c); + return new Color((int) r, (int) g, (int) b); + } + + public static int[] countOccurences(char[] alphabet, String input) + { + int[] count = new int[alphabet.length]; + + for (int i = 0; i < alphabet.length; i++) + count[i] = 0; + + for (char c : input.toCharArray()) + for (int i = 0; i < alphabet.length; i++) + if (alphabet[i] == c) + count[i]++; + + /* We could skip right to the next input character as soon as we + * find a match but this implementation supports multiple occurences + * of a char in the alphabet (inefficiently) + */ + + return count; + } +} diff --git a/ws2015/eip/blaetter/05/manifest b/ws2015/eip/blaetter/05/manifest index 0573ab5..b858ad4 100644 --- a/ws2015/eip/blaetter/05/manifest +++ b/ws2015/eip/blaetter/05/manifest @@ -1 +1,2 @@ +Histogramm.java H5-2.pdf \ No newline at end of file -- cgit v1.2.3