#!/usr/bin/env python import sys, re def normalize_text (text): ret = text.lower ().replace ("ä", "ae").replace ("ö", "oe" ).replace ("ü", "ue").replace ("ß", "ss") ret = re.sub ("[^a-z]+", "", ret) return ret def encode (text, key): keys = map (lambda x: ord (x) - ord ('a'), key) res = "" for i in range (len (text)): l = ord (text[i]) - ord ('a') res += chr (((l + keys[i % len (keys)]) % 26) + ord ('a')) return res def letter_distribution (text): length = len (text) ret = {} for i in text: ret[i] = 1.0 / length + ret.get (i, 0) return ret def index_of_coincidence (text1, text2): assert len (text1) == len (text2) count = 0.0 for i in range (len (text1)): if text1[i] == text2[i]: count += 1 return float (count) / len (text1) text = """ Es war einmal ein armer Bauer namens Krebs, der fuhr mit zwei Ochsen ein Fuder Holz in die Stadt und verkaufte es für zwei Taler an einen Doktor. Wie ihm nun das Geld ausbezahlt wurde, saß der Doktor gerade zu Tisch; da sah der Bauer, wie er schön aß und trank, und das Herz ging ihm danach auf, und er wäre auch gern ein Doktor gewesen. Also blieb er noch ein Weilchen stehen und fragte endlich, ob er nicht auch könnte ein Doktor werden. "O ja", sagte der Doktor, "das ist bald geschehen." "Was muß ich tun?" fragte der Bauer. "Erstlich kauf dir ein Abecebuch, so eins, wo vorn ein Gockelhahn drin ist; zweitens mache deinen Wagen und deine zwei Ochsen zu Geld und schaff dir damit Kleider an und was sonst zur Doktorei gehört; drittens laß dir ein Schild malen mit den Worten: ,Ich bin der Doktor Allwissend' und laß das oben über deine Haustür nageln!" Der Bauer tat alles, wies ihm geheißen war. Als er nun ein wenig gedoktert hatte, aber noch nicht viel, ward einem reichen, großen Herrn Geld gestohlen. Da ward ihm von dem Doktor Allwissend gesagt, der in dem und dem Dorfe wohnte und auch wissen müßte, wo das Geld hingekommen wäre. Also ließ der Herr seinen Wagen anspannen, fuhr hinaus ins Dorf und fragte bei ihm an, ob er der Doktor Allwissend wäre. Ja, der wär er. So sollte er mitgehen und das gestohlene Geld wieder schaffen. O ja, aber die Grete, seine Frau müßte auch mit. Der Herr war damit zufrieden und ließ sie beide in den Wagen sitzen, und sie fuhren zusammen fort. Als sie auf den adligen Hof kamen, war der Tisch gedeckt; da sollte er erst mitessen. Ja, aber seine Frau, die Grete, auch, sagte er und setzte sich mit ihr hinter den Tisch. Wie nun der erste Bediente mit einer Schüssel schönem Essen kam, stieß der Bauer seine Frau an und sagte: Grete, das war der erste", und meinte, es wäre derjenige, welcher das erste Essen brächte. Der Bediente aber meinte, er hätte damit sagen wollen: Das ist der erste Dieb; und weil er's nun wirklich war, ward ihm angst, und er sagte draußen zu seinen Kameraden: Der Doktor weiß alles, wir kommen übel an; er hat gesagt, ich wäre der erste." Der zweite wollte gar nicht herein, er mußte aber doch. Wie er nun mit seiner Schüssel herein kam, stieß der Bauer seine Frau an: Grete, das ist der zweite." Dem Bedienten ward ebenfalls angst, und er machte, daß er hinauskam. Dem dritten ging's nicht besser; der Bauer sagte wieder: Grete, das ist der dritte." Der vierte mußte eine verdeckte Schüssel hereintragen, und der Herr sprach zum Doktor, er sollte seine Kunst zeigen und raten, was darunter läge; es waren aber Krebse. Der Bauer sah die Schüssel an, wußte nicht, wie er sich helfen sollte, und sprach: Ach, ich armer Krebs!" Wie der Herr das hörte, rief er: Da, er weiß es, nun weiß er auch, wer das Geld hat." Dem Bedienten aber ward gewaltig angst, und er blinzelte den Doktor an, er möchte einmal herauskommen. Wie er nun hinauskam, gestanden sie ihm alle viere, sie hätten das Geld gestohlen; sie wolltens ja gerne herausgeben und ihm eine schwere Summe dazu, wenn er sie nicht verraten wollte; es ginge ihnen sonst an den Hals. Sie führten ihn auch hin, wo das Geld versteckt lag. Damit war der Doktor zufrieden, ging wieder hinein, setzte sich an den Tisch und sprach: Herr, nun will ich in meinem Buch suchen, wo das Geld steckt." Der fünfte Bediente aber kroch in den Ofen und wollte hören, ob der Doktor noch mehr wüßte. Der saß aber und schlug sein Abecebuch auf, blätterte hin und her und suchte den Gockelhahn. Weil er ihn nicht gleich finden konnte, sprach er: Du bist doch darin und mußt auch heraus." Da glaubte der im Ofen, er wäre gemeint, sprang voller Schrecken heraus und rief: Der Mann weiß alles." Nun zeigte der Doktor Allwissend dem Herrn, wo das Geld lag, sagte aber nicht, wers gestohlen hatte, bekam von beiden Seiten viel Geld zur Belohnung und ward ein berühmter Mann. """ codewort = "labertasche" if len (sys.argv) >= 3: codewort = sys.argv[1] text = open (sys.argv[2]).read () elif len (sys.argv) == 2: codewort = sys.argv[1] simpletext = normalize_text (text) rel_h = letter_distribution (simpletext) code = encode (simpletext, codewort) print "Häufigkeitsverteilung im Originaltext" ci = 0 keys = rel_h.keys () keys.sort () for k in keys: v = rel_h [k] ci += v**2 print "%s: %5.2f %% - %d" % (k, 100.0 * v, v * len (simpletext)) print print "Index of Coincidence des Originaltextes" print "%5.2f %%" % (100.0 * ci) print print "Index of Coincidence einer gleichverteilten Buchstabenfolge" print "%5.2f %%" % (100.0 / 26) print middle = (ci + 1.0 / 26) / 2 print "Coincidence-Diagramm:" for i in range (1, 51): ci = index_of_coincidence (code, code[i:] + code[:i]) print "%2d: %5.2f, %s" % (i, ci * 100, (["*", "­"][ci <= middle]) * int (round (ci * 100)))