Hallo zusammen,
ich hoffe, mir kann vielleicht jemand helfen. Ich beschäftige mich gerade mit der Analyse von Strings. Dabei bin auf die sog. Schreibmaschinendistanz gestoßen.
Diese drückt den Abstand von zwei Buchstaben auf der - im dt. QWERTZ-Tastaturbelegung - aus.
Beispielsweise sind die Buchstaben ‚u‘ und ‚i‘ direkt nebeneinander.
Sie haben den Abstand 1. Um vom ‚h‘ zum ‚k‘ zu gelangen, muss man über das ‚j‘ gehen. Der Abstand ist 2.
Hund wäre demnach: H - > U (1); U ->N (2); N->D (4) = Distanz 7.
Ich suche nun ein Snippet, welches die Schreibmaschinendistanz berechnen kann.
Ich bin leider bisher total erfolglos geblieben und suche daher Unterstützung.
Danke Euch!
Gerne auch für weitere Hinweise!
Schreibmaschinendistanz
Du bist darauf gestoßen? Wozu willst du die denn verwenden? Oder hast du das als Aufgabe bekommen?
Zur Lösung könnte man zb die drei Zeilen der quertz-Belegung als Listen anlegen. Für zwei gegebene Buchstaben ist der Abstand dann die Differenz ihrer Listen Position. Sind die Listen nicht dieselben, muss man dann noch 1 oder 2 addieren, je nach dem in welcher Liste sie stecken.
Zur Lösung könnte man zb die drei Zeilen der quertz-Belegung als Listen anlegen. Für zwei gegebene Buchstaben ist der Abstand dann die Differenz ihrer Listen Position. Sind die Listen nicht dieselben, muss man dann noch 1 oder 2 addieren, je nach dem in welcher Liste sie stecken.
Zum Glück sind die Zeiten mit Aufgaben bekommen vorbei:) Ursprünglich habe ich mich mal mit Dubletten bei einem Verein beschäftigt und bin an dem Thema immer mal wieder hängengeblieben....
Ich verstehe Deinen Ansatz!
Aber wie ist das dann mit ü und ä. Diese sind ja eigentlich nur 1 entfernt. Mit der Listenaddition wären sie doch dann 2 entfernt, oder?
Danke Dir schon mal!
Ich verstehe Deinen Ansatz!
Aber wie ist das dann mit ü und ä. Diese sind ja eigentlich nur 1 entfernt. Mit der Listenaddition wären sie doch dann 2 entfernt, oder?
Danke Dir schon mal!
Die sind so weit entfernt wie du sie in die Listen packst. Letztlich ist dieses Maß ja nicht wirklich sinnvoll beziehungsweise schlecht definiert. Die Tasten sind ja eigentlich versetzt, aber die Distanz reflektiert das ja auch nicht.
@PyPankow: Es gibt eine Norm dafür: Die Reihen sind jeweils um ¼ Tastenbreite verschoben, bzw. ½ zwischen den Zahlen und der Q-Reihe, ¼ zwischen der Q- und A-Reihe und ½ zwischen A und Y. Weil die Hebel Platz brauchen. 

Hmm, eigentlich spannend:
Mit networx (leider ohne die tatsächliche Entfernung zu erhalten)
Oder "Bruteforce" wie im Video erwähnt:
Mit networx (leider ohne die tatsächliche Entfernung zu erhalten)
Code: Alles auswählen
from itertools import pairwise
import networkx as nx
WORD = "HUND"
def setup_network():
top = list("QWERTZUIOPÜ")
middle = list("ASDFGHJKLÖÄ")
bottom = list("YXCVBNM")
keyboard = nx.Graph()
keyboard.add_nodes_from(top)
keyboard.add_nodes_from(middle)
keyboard.add_nodes_from(bottom)
keyboard.add_edges_from(pairwise(top))
keyboard.add_edges_from(pairwise(middle))
keyboard.add_edges_from(pairwise(bottom))
keyboard.add_edges_from(zip(top, middle))
keyboard.add_edges_from(zip(top[1:], middle))
keyboard.add_edges_from(zip(middle, bottom))
keyboard.add_edges_from(zip(middle[1:], bottom))
return keyboard
def main():
keyboard = setup_network()
paths = [nx.shortest_path(keyboard, previous_letter, next_letter) for previous_letter, next_letter in pairwise(WORD)]
print(paths)
distances = [len(path) - 1 for path in paths]
print(distances)
total_distance = sum(distances)
print(total_distance)
main()
"""
[['H', 'U'], ['U', 'H', 'N'], ['N', 'B', 'V', 'C', 'D']]
[1, 2, 4]
7
"""
Code: Alles auswählen
import math
from itertools import product, pairwise
WORD = "HUND"
def main():
full_distance = 19.05
quarter_distance = 19.05 * 0.25
half_distance = 19.05 * 0.5
top = {letter: (num * full_distance, 0) for num, letter in enumerate("QWERTZUIOPÜ")}
middle = {letter: (num * full_distance + quarter_distance, full_distance) for num, letter in enumerate("ASDFGHJKLÖÄ")}
bottom = {letter: (num * full_distance + quarter_distance + half_distance, 2 * full_distance) for num, letter in enumerate("YXCVBNM")}
keys = top | middle | bottom
letter_distances = {(this, other): math.sqrt((tx - ox) ** 2 + (ty - oy) ** 2) for (this, (tx, ty)), (other, (ox, oy)) in product(keys.items(), repeat=2)}
word_letter_distances = {
(previous_letter, next_letter): letter_distances[(previous_letter, next_letter)] for previous_letter, next_letter in pairwise(WORD)
}
for (this, other), distance in word_letter_distances.items():
print(f"{this} -> {other}: {distance:0.2f} mm")
print(f"Total: {sum(word_letter_distances.values()):0.2f} mm")
main()
"""
H -> U: 23.81 mm
U -> N: 38.40 mm
N -> D: 69.34 mm
Total: 131.55 mm
"""
Hallo,
ich habe jetzt das Problem, dass ich pairwise in PyCharm nicht importieren kann. Ich habe bereits nach Alternativen recherchiert, leider alles ohne Erfolg.
Auch hier https://docs.python.org/2/library/itertools.html finde ich nichts dazu. Habt Ihr einen Tipp für mich? Herzlichen Dank!
ich habe jetzt das Problem, dass ich pairwise in PyCharm nicht importieren kann. Ich habe bereits nach Alternativen recherchiert, leider alles ohne Erfolg.
Auch hier https://docs.python.org/2/library/itertools.html finde ich nichts dazu. Habt Ihr einen Tipp für mich? Herzlichen Dank!
PyCharm hat damit nichts zu tun, das ist nur die IDE. Du benutzt eine zu alte Pythonversion. `pairwise` gibt es erst ab Python 3.10.
Die Dokumentation, die Du verlinkt hast, ist für Python2 und das benutzt Du hoffentlich nicht mehr.
https://docs.python.org/3/library/itert ... s.pairwise
Die Dokumentation, die Du verlinkt hast, ist für Python2 und das benutzt Du hoffentlich nicht mehr.
https://docs.python.org/3/library/itert ... s.pairwise
- __blackjack__
- User
- Beiträge: 13939
- Registriert: Samstag 2. Juni 2018, 10:21
- Wohnort: 127.0.0.1
- Kontaktdaten:
Ansonsten gibt es `pairwise()` für Python <3.10 auch im externen `more_itertools`-Modul.
“Java is a DSL to transform big Xml documents into long exception stack traces.”
— Scott Bellware
— Scott Bellware
Ach, manchmal! Tausend Dank!
Ich habe jetzt Python aktualisiert und über more_itertools pairwise importiert. Das klappt!
Ich knobel jetzt noch an der letzten Fehlermeldung, die ich in myCharm bekomme, wenn ich die Printbefehle nach def ergänze....
print(f"Total: {sum(word_letter_distances.values()):0.2f} mm")
print("Hier endet der Code")
Fehlermeldung:
n <module>
print(f"Total: {sum(word_letter_distances.values()):0.2f} mm")
NameError: name 'word_letter_distances' is not defined
Ich habe jetzt Python aktualisiert und über more_itertools pairwise importiert. Das klappt!
Ich knobel jetzt noch an der letzten Fehlermeldung, die ich in myCharm bekomme, wenn ich die Printbefehle nach def ergänze....
print(f"Total: {sum(word_letter_distances.values()):0.2f} mm")
print("Hier endet der Code")
Fehlermeldung:
n <module>
print(f"Total: {sum(word_letter_distances.values()):0.2f} mm")
NameError: name 'word_letter_distances' is not defined
Danke! Das ist im Grunde der Code von oben, angepasst beim Import und eben die zwei Print-Befehle
Ohne die vorletzte Zeile gibt es keinen Fehler, aber auch kein Ergebnis......
Ohne die vorletzte Zeile gibt es keinen Fehler, aber auch kein Ergebnis......
Code: Alles auswählen
#from itertools import pairwise
from itertools import product
from more_itertools import pairwise
import math
WORD = "HUND"
def main():
full_distance = 19.05
quarter_distance = 19.05 * 0.25
half_distance = 19.05 * 0.5
top = {letter: (num * full_distance, 0) for num, letter in enumerate("QWERTZUIOPÜ")}
middle = {letter: (num * full_distance + quarter_distance, full_distance) for num, letter in enumerate("ASDFGHJKLÖÄ")}
bottom = {letter: (num * full_distance + quarter_distance + half_distance, 2 * full_distance) for num, letter in enumerate("YXCVBNM")}
keys = top | middle | bottom
letter_distances = {(this, other): math.sqrt((tx - ox) ** 2 + (ty - oy) ** 2) for (this, (tx, ty)), (other, (ox, oy)) in product(keys.items(), repeat=2)}
word_letter_distances = {
(previous_letter, next_letter): letter_distances[(previous_letter, next_letter)] for previous_letter, next_letter in pairwise(WORD)
}
for (this, other), distance in word_letter_distances.items():
print(f"{this} -> {other}: {distance:0.2f} mm")
print(f"Total: {sum(word_letter_distances.values()):0.2f} mm")
print(f"Total: {sum(word_letter_distances.values()):0.2f} mm")
print("Hier endet der Code")
Weil es auf Modulebene kein "word_letter_distances" gibt. Und das ist auch richtig so.
Wenn das dein ganzes Script ist, wo genau rufst du da die Funktion main() auf?
In der Regel sieht der Eintiegspunkt dafür am Ende des Scripts so aus:
Auf Modulebene (also ohne Einrückung) stehen nur Importe, die Definition von Konstanten, Klassen und Funktionen und eben am Ende des Scripts dieser Zweizeiler um die Funktion main aufzurufen.
Wenn das dein ganzes Script ist, wo genau rufst du da die Funktion main() auf?
In der Regel sieht der Eintiegspunkt dafür am Ende des Scripts so aus:
Code: Alles auswählen
if __name__ == "__main__":
main()
- __blackjack__
- User
- Beiträge: 13939
- Registriert: Samstag 2. Juni 2018, 10:21
- Wohnort: 127.0.0.1
- Kontaktdaten:
@PyPankow: `word_letter_distances` ist *in* der Funktion definiert. Du versuchst ausserhalb der Funktion darauf zuzugreifen wo es halt undefiniert ist. Und in der Funktion steht diese Zeile doch bereits‽
Was bei dem Code fehlt ist der Aufruf der `main()`-Funktion. Wenn man Funktionen nicht aufruft, dann passiert auch nix. Also am Ende statt der `print()`-Zeilen:
Was bei dem Code fehlt ist der Aufruf der `main()`-Funktion. Wenn man Funktionen nicht aufruft, dann passiert auch nix. Also am Ende statt der `print()`-Zeilen:
Code: Alles auswählen
if __name__ == "__main__":
main()
“Java is a DSL to transform big Xml documents into long exception stack traces.”
— Scott Bellware
— Scott Bellware
Erneut ein Danke! Ich habe jetzt getüftelt und in myCharm die Main Funktion eingebaut. Sie greift auch auf das Modul/Funktion distanz zu.
Der Code dafür sieht so aus. Ja.. Einstiegsniveau...
Die Fehlermeldung hat sich sich jetzt verändert und meldet nicht unterstützte Operatoren. Da bin ich ehrlich gesagt überfragt. Frage mich, warum der Fehler bei mir kommt. Stichwort Versionen oder fehlt eine lib oder oder oder.... Die Operatoren müssten doch unterstützt werden...
Der Code dafür sieht so aus. Ja.. Einstiegsniveau...

Code: Alles auswählen
import distanz
if __name__ == "__main__":
distanz.WORD
print(distanz.WORD)
print(distanz.pairwise("fgdgf"))
print(distanz.distanz())
Code: Alles auswählen
line 20, in distanz
keys = top | middle | bottom
TypeError: unsupported operand type(s) for |: 'dict' and 'dict'
noe, der |-Operator ist zumindest auch bei mir fuer dicts nicht unterstuetzt. Ich habe Python 3.8. Kann sein, dass neuere Pythons den unterstuetzen. Den kanst du dir aber auch trivial nachbauen, durch ein leeres dict und zwei update calls. Das ist ja nur Kombination aus allen Eintraegen.
Das ist neu in 3.9: https://docs.python.org/3/whatsnew/3.9. ... -operators