diff options
| -rw-r--r-- | ws2015/eip/blaetter/05/Histogramm.java | 111 | ||||
| -rw-r--r-- | ws2015/eip/blaetter/05/manifest | 1 |
2 files changed, 112 insertions, 0 deletions
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 @@ | |||
| 1 | import java.awt.Rectangle; | ||
| 2 | import java.awt.Color; | ||
| 3 | import java.awt.Point; | ||
| 4 | |||
| 5 | class Histogramm { | ||
| 6 | |||
| 7 | public static final int SPACING = 1; | ||
| 8 | public static final int MIN_BAR_WIDTH = 2; | ||
| 9 | public static final int HEIGHT = 480; | ||
| 10 | public static final int LABEL_HEIGHT = 12; | ||
| 11 | public static final int MIN_WIDTH = 640; | ||
| 12 | |||
| 13 | public static final Color COLD = Color.blue; | ||
| 14 | public static final Color HOT = Color.red; | ||
| 15 | |||
| 16 | public static void main(String[] args) | ||
| 17 | { | ||
| 18 | if (args.length < 2) | ||
| 19 | { | ||
| 20 | System.err.println("Need at least two arguments"); | ||
| 21 | System.exit(2); | ||
| 22 | } | ||
| 23 | |||
| 24 | String input = ""; | ||
| 25 | for (int i = 1; i < args.length; i++) | ||
| 26 | input += args[i]; | ||
| 27 | |||
| 28 | char[] alphabet = args[0].toCharArray(); | ||
| 29 | // We convert to char[] instead of byte[] in order to be unicode aware | ||
| 30 | |||
| 31 | graph(alphabet, makeRelative(countOccurences(alphabet, input))); | ||
| 32 | // Why can’t we have nice things? Like function composition? | ||
| 33 | } | ||
| 34 | |||
| 35 | public static double[] makeRelative (int[] counts) | ||
| 36 | { | ||
| 37 | double[] relativeCounts = new double[counts.length]; | ||
| 38 | int max = 0; | ||
| 39 | |||
| 40 | // I'm sure there's a library function for this but I was too lazy to look | ||
| 41 | for (int c : counts) | ||
| 42 | if (c > max) | ||
| 43 | max = c; | ||
| 44 | |||
| 45 | for (int i = 0; i < counts.length; i++) | ||
| 46 | relativeCounts[i] = ((double) counts[i]) / max; | ||
| 47 | |||
| 48 | return relativeCounts; | ||
| 49 | } | ||
| 50 | |||
| 51 | public static void graph(char[] alphabet, double[] counts) | ||
| 52 | { | ||
| 53 | int minWidth = MIN_BAR_WIDTH * (counts.length) + SPACING * (counts.length - 1); | ||
| 54 | int width = Math.max(minWidth, MIN_WIDTH); | ||
| 55 | |||
| 56 | int barWidth = (width - SPACING * (counts.length - 1)) / counts.length; | ||
| 57 | |||
| 58 | GraphicsWindow gw = new GraphicsWindow(width, HEIGHT); | ||
| 59 | gw.setText("Histogramm"); | ||
| 60 | |||
| 61 | int x = 0; | ||
| 62 | |||
| 63 | for (int i = 0; i < counts.length; i++) | ||
| 64 | { | ||
| 65 | int height = (int) (counts[i] * HEIGHT); | ||
| 66 | Point corner = new Point(x, HEIGHT - height); | ||
| 67 | Rectangle bar = new Rectangle(corner.x, corner.y, barWidth, height); | ||
| 68 | boolean labelAbove = height <= LABEL_HEIGHT; | ||
| 69 | |||
| 70 | |||
| 71 | gw.setColor(color(counts[i])); | ||
| 72 | gw.fill(bar); | ||
| 73 | gw.setColor(labelAbove ? Color.black : Color.white); | ||
| 74 | gw.drawStringAt(String.format("%c", alphabet[i]), new Point(corner.x, corner.y + (labelAbove ? -5 : LABEL_HEIGHT))); | ||
| 75 | |||
| 76 | x += SPACING + barWidth; | ||
| 77 | } | ||
| 78 | |||
| 79 | gw.mouseClick(); | ||
| 80 | System.exit(0); | ||
| 81 | } | ||
| 82 | |||
| 83 | public static Color color(double c) | ||
| 84 | { | ||
| 85 | double r, g, b; | ||
| 86 | r = HOT.getRed() * c + COLD.getRed() * (1 - c); | ||
| 87 | g = HOT.getGreen() * c + COLD.getGreen() * (1 - c); | ||
| 88 | b = HOT.getBlue() * c + COLD.getBlue() * (1 - c); | ||
| 89 | return new Color((int) r, (int) g, (int) b); | ||
| 90 | } | ||
| 91 | |||
| 92 | public static int[] countOccurences(char[] alphabet, String input) | ||
| 93 | { | ||
| 94 | int[] count = new int[alphabet.length]; | ||
| 95 | |||
| 96 | for (int i = 0; i < alphabet.length; i++) | ||
| 97 | count[i] = 0; | ||
| 98 | |||
| 99 | for (char c : input.toCharArray()) | ||
| 100 | for (int i = 0; i < alphabet.length; i++) | ||
| 101 | if (alphabet[i] == c) | ||
| 102 | count[i]++; | ||
| 103 | |||
| 104 | /* We could skip right to the next input character as soon as we | ||
| 105 | * find a match but this implementation supports multiple occurences | ||
| 106 | * of a char in the alphabet (inefficiently) | ||
| 107 | */ | ||
| 108 | |||
| 109 | return count; | ||
| 110 | } | ||
| 111 | } | ||
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 @@ | |||
| 1 | Histogramm.java | ||
| 1 | H5-2.pdf \ No newline at end of file | 2 | H5-2.pdf \ No newline at end of file |
