# Words by the Numbers 3, Exercise 3: how far apart the language profiles are. TRAIN = { "English": ( "The old harbour was quiet in the early morning, and the fishermen were " "already mending their nets on the stone quay. A cold wind came in from " "the sea, carrying the smell of salt and tar, while the children of the " "village walked slowly to school with their books under their arms. " "Nobody spoke much, for the week had been long and the weather had been " "hard on everyone who worked on the water." ), "French": ( "Le vieux port était calme au petit matin, et les pêcheurs réparaient " "déjà leurs filets sur le quai de pierre. Un vent froid venait de la mer, " "apportant l'odeur du sel et du goudron, pendant que les enfants du " "village marchaient lentement vers l'école, leurs livres sous le bras. " "Personne ne parlait beaucoup, car la semaine avait été longue et le " "temps avait été dur pour tous ceux qui travaillaient sur l'eau." ), "German": ( "Der alte Hafen war am frühen Morgen still, und die Fischer flickten " "schon ihre Netze am steinernen Kai. Ein kalter Wind kam vom Meer und " "brachte den Geruch von Salz und Teer mit, während die Kinder des Dorfes " "langsam zur Schule gingen, ihre Bücher unter dem Arm. Niemand sprach " "viel, denn die Woche war lang gewesen und das Wetter hatte allen " "zugesetzt, die auf dem Wasser arbeiteten." ), "Spanish": ( "El viejo puerto estaba tranquilo a primera hora de la mañana, y los " "pescadores ya remendaban sus redes en el muelle de piedra. Un viento " "frío llegaba del mar, trayendo el olor a sal y alquitrán, mientras los " "niños del pueblo caminaban despacio hacia la escuela con los libros " "bajo el brazo. Nadie hablaba mucho, porque la semana había sido larga " "y el tiempo había sido duro para todos los que trabajaban en el agua." ), "Italian": ( "Il vecchio porto era tranquillo di primo mattino, e i pescatori " "rammendavano già le loro reti sulla banchina di pietra. Un vento freddo " "veniva dal mare, portando l'odore di sale e di catrame, mentre i " "bambini del villaggio camminavano lentamente verso la scuola con i " "libri sotto il braccio. Nessuno parlava molto, perché la settimana era " "stata lunga e il tempo era stato duro per tutti quelli che lavoravano " "sull'acqua." ), } TEST = { "English": ( "She opened the window and listened to the rain falling on the roof of " "the little house, thinking about the letter that had arrived the day " "before and what she should write in answer to it." ), "French": ( "Elle ouvrit la fenêtre et écouta la pluie qui tombait sur le toit de la " "petite maison, en pensant à la lettre qui était arrivée la veille et à " "ce qu'elle devait écrire en réponse." ), "German": ( "Sie öffnete das Fenster und hörte dem Regen zu, der auf das Dach des " "kleinen Hauses fiel, und dachte an den Brief, der am Tag zuvor " "angekommen war, und was sie darauf antworten sollte." ), "Spanish": ( "Ella abrió la ventana y escuchó la lluvia que caía sobre el tejado de " "la casita, pensando en la carta que había llegado el día anterior y en " "lo que debía escribir como respuesta." ), "Italian": ( "Lei aprì la finestra e ascoltò la pioggia che cadeva sul tetto della " "piccola casa, pensando alla lettera che era arrivata il giorno prima e " "a cosa dovesse scrivere in risposta." ), } import string import unicodedata from collections import Counter from itertools import combinations from pydoc_data.topics import topics ALPHA = string.ascii_lowercase def profile(text): decomposed = unicodedata.normalize("NFD", text.lower()) letters = [ch for ch in decomposed if ch in ALPHA] counts = Counter(letters) return [counts[ch] / len(letters) for ch in ALPHA] def distance(p, q): return sum(abs(a - b) for a, b in zip(p, q)) profiles = {lang: profile(text) for lang, text in TRAIN.items()} pairs = sorted( (distance(profiles[a], profiles[b]), a, b) for a, b in combinations(profiles, 2) ) print("closest pairs:") for d, a, b in pairs[:3]: print(f" {a:8} {b:8} {d:.3f}") print("furthest pair:", pairs[-1][1], pairs[-1][2], f"{pairs[-1][0]:.3f}") # A different kind of English: the Python reference documentation. docs = profile(" ".join(topics.values())) print("story English vs doc English:", f"{distance(profiles['English'], docs):.3f}") for lang in ("French", "German", "Spanish", "Italian"): print(f"doc English vs {lang}:", f"{distance(docs, profiles[lang]):.3f}") # Output when run (Python 3.14; the documentation-text figures depend on the Python version): # closest pairs: # Spanish Italian 0.310 # English German 0.350 # French Italian 0.372 # furthest pair: German Spanish 0.607 # story English vs doc English: 0.347 # doc English vs French: 0.393 # doc English vs German: 0.412 # doc English vs Spanish: 0.449 # doc English vs Italian: 0.403