summaryrefslogtreecommitdiff
path: root/ws2015/eip/blaetter/05/Histogramm.java
diff options
context:
space:
mode:
Diffstat (limited to 'ws2015/eip/blaetter/05/Histogramm.java')
-rw-r--r--ws2015/eip/blaetter/05/Histogramm.java111
1 files changed, 111 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 @@
1import java.awt.Rectangle;
2import java.awt.Color;
3import java.awt.Point;
4
5class 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}