Vorheriges Thema anzeigen :: Nächstes Thema anzeigen |
Autor |
Nachricht |
Wolle-77 •--->


Anmeldedatum: 25.02.2003 Beiträge: 449 Wohnort: Geldern
|
Verfasst am: 26.07.2007 - 21:44 Titel: Römische und arabische Zahlen |
|
|
Hallo zusammen,
nachdem das Niveau in diesem Forum in letzter Zeit ziemlich gesunken ist (will ja nicht rumätzen oder mich über etwas stellen, aber ich frage mich wirklich, ob das sein muß und was das und vor allem wem das dienlich sein soll...!), stelle ich mal was neues ein.
Habe mich heute gefragt, wie wohl Programme wie XPress und InDesign bei der Seitenpaginierung intern vorgehen, wenn der Nutzer römische Paginierung auswählt.
Ausgangspunkt war, daß ich die Dateien eines Prospektes spaßeshalber römisch paginieren wollte (nur acht Seiten), es dann aber doch arabisch (also Hilfspagina) gelassen habe, da der Renamer4Mac interessanter Weise keine römischen Zahlen kann (wohl aber A, B, C...). Ob so ein Algorithmus schwierig war?
Nach diverser Internetrecherche und nur wenigen Ansätzen, die laut Bekunden alle kompliziert sind, habe ich es selbst neu versucht und finde, eine vor allem kurze und sehr effektive Methode gefunden zu haben.
Folgende zwei Handler habe ich erstellt:
Code: | on arab2rom(zahl, minomax) -- © Copyright 26.7.2007 by Martin Wolter, martin_wolter@gmx.de
set romzahl to ""
if minomax is false then
set romliste to {"m", 1000, "d", 500, "c", 100, "l", 50, "x", 10, "v", 5, "i", 1}
else
set romliste to {"M", 1000, "D", 500, "C", 100, "L", 50, "X", 10, "V", 5, "I", 1}
end if
repeat with i from 1 to (count items of romliste) by 2
set zeichen to item i of romliste
set wert to item (i + 1) of romliste
repeat until zahl < wert
set romzahl to romzahl & zeichen
set zahl to zahl - wert
end repeat
end repeat
if minomax is false then
set romzahl to do shell script "echo " & romzahl & " | sed -e 's/dcccc/cm/g' -e 's/cccc/cd/g' -e 's/lxxxx/xc/g' -e 's/xxxx/xl/g' -e 's/viiii/ix/g' -e 's/iiii/iv/g'"
else
set romzahl to do shell script "echo " & romzahl & " | sed -e 's/DCCCC/CM/g' -e 's/CCCC/CD/g' -e 's/LXXXX/XC/g' -e 's/XXXX/XL/g' -e 's/VIIII/IX/g' -e 's/IIII/IV/g'"
end if
return romzahl
end arab2rom |
und das Gegenstück, zur Rückwandlung:
Code: | on rom2arab(romzahl) -- © Copyright 26.7.2007 by Martin Wolter, martin_wolter@gmx.de
set zahl to 0
set romzahl to do shell script "echo " & romzahl & " | sed -e 'y/mdclxvi/MDCLXVI/' -e 's/CM/DCCCC/g' -e 's/CD/CCCC/g' -e 's/XC/LXXXX/g' -e 's/XL/XXXX/g' -e 's/IX/VIIII/g' -e 's/IV/IIII/g'"
set romliste to {"M", 1000, "D", 500, "C", 100, "L", 50, "X", 10, "V", 5, "I", 1}
repeat with i from 1 to (count items of romliste) by 2
set my text item delimiters to (item i of romliste)
set zahl to zahl + ((count of text items of romzahl) - 1) * (item (i + 1) of romliste)
end repeat
return zahl
end rom2arab |
Was meint Ihr? Geht es noch kürzer oder hättet Ihr es anders gemacht?
Ich bin damit nach ausgiebigen Tests erstmal sehr zufrieden. _________________ Martin Wolter
--
Apple rocks the planet! |
|
Nach oben |
|
 |
Skeeve •---->


Anmeldedatum: 20.04.2006 Beiträge: 1067
|
Verfasst am: 30.07.2007 - 22:23 Titel: |
|
|
Mit reinem AppleScript (Hin-Richtung)
Zitat: | on arab2rom(zahl, lower)
if lower then
set rom_chr to characters of "ivxlcdm"
else
set rom_chr to characters of "IVXLCDM"
end if
set rom_pat to {"0", "00", "000", "01", "1", "10", "100", "1000", "02"}
set rom to ""
set d to 1000
set f to zahl div d
set zahl to zahl - f * d
repeat while f > 0
set rom to rom & item 7 of rom_chr
set f to f - 1
end repeat
set i to 5
repeat while d > 1
set d to d / 10
set f to zahl div d
if f > 0 then
set zahl to zahl - f * d
repeat with o in every character of item f of rom_pat
set rom to rom & item (i + o) of rom_chr
end repeat
end if
set i to i - 2
end repeat
return rom
end arab2rom |
_________________ "All problems are solved in slightly less than half an hour" (Chumbawamba, "Hey Hey We're The Junkies") |
|
Nach oben |
|
 |
Wolle-77 •--->


Anmeldedatum: 25.02.2003 Beiträge: 449 Wohnort: Geldern
|
Verfasst am: 28.02.2008 - 15:00 Titel: Die Wiederentdeckung des reinen AppleScript's |
|
|
So, nach langer Zeit habe ich heute tatsächlich mal meinen handler gebrauch, es ging darum, ein kleines Werk umzupaginieren.
Und die DTP ist dann zu mir gekommen, da der Renamer4Mac diese Funktion nicht bietet.
Während das Werk ruckzuck damit bearbeitet war (aber was heißt schon ruckzuck…?), habe ich noch etwas über den handler nachgedacht und da ich auch schon dem Entwickler von Renamer4Mac diesen geschickt habe und der sich aber nicht gemeldet habe, meinte mein Kollege nur, daß er für den Renamer evtl. zu langsam ist – und mit einem Test von 7.000 Durchläufen kam ich auch auf unglaublich lange 57 Sekunden (nicht repräsentativ, iMac 24 ").
Das ist echt zu lange. Und der Kollege meinte auch nur, als C-Programm wäre sowas rasend schnell und ein Klacks; selbst bei 100.000 Durchläufen (damit bin ich angefangen und habe aber auf 7.000 reduziert, da es einfach zu lange dauerte).
Dann hat er tatsächlich eine kleine C-Routine gefunden (499 Byte), die mit gcc kompiliert zu einem 16 KB kleinen Shell-Programm auch via do shell script aufrufbar war.
Und die große Überraschung (zu meiner Genugtuung, erstmal): Es dauerte ganze 8 Sekunden länger, nämlich 65 Sekunden.
Und eine Kupplung zu do shell habe ich ja auch drin in meinem obigen Originalhandler. Also was dauert es soviel länger?
Naja, aber der Kern der Sache ist, in der C-Routine war ein anderer Ansatz: Anstatt erstmal mit den 7 eigentlichen Zahlen (M, D, C, L, X, V, I) zu verfahren und anschließend diese noch um die Sonderfälle CM, CD, XC, XL, IX und IV zu reduzieren, wurde dort direkt das gleiche Prinzip der so-lange-Reduzierens-bis-der-Wert-kleiner-als-die-noch-verbliebene-Zahl-ist-Methode angewendet.
Also: Warum brauche ich da noch die shell, um sed zum Such-Tausch zu benutzen?
So gerne ich diese in den letzten Monaten benutze und fast ohne nicht mehr auskam, so habe ich mir meinen handler noch einmal vorgenommen.
Hier das Ergebnis:
Code: | on arab2rom(zahl) -- © Copyright 26.7.2007 by Martin Wolter, martin_wolter@gmx.de
set romzahl to ""
set romliste to {"M", 1000, "CM", 900, "D", 500, "CD", 400, "C", 100, "XC", 90, "L", 50, "XL", 40, "X", 10, "IX", 9, "V", 5, "IV", 4, "I", 1}
repeat with i from 1 to 26 by 2
set zeichen to item i of romliste
set wert to item (i + 1) of romliste
if zahl is greater than or equal to wert then
repeat until zahl < wert
set romzahl to romzahl & zeichen
set zahl to zahl - wert
end repeat
end if
end repeat
return romzahl
end arab2rom |
Voilá! Extrem kurz vom Quellcode und die 7000 Durchläufe schafft er in ca. 1 Sekunde! Also, äh, @Skeeve: Deinen damals als Antwort geposteten handler verstehe ich erstens nicht so richtig und zweitens braucht der 8 Sekunden…
Sehr schön!
Man könnte die if-Abfrage im ersten repeat auch noch weglassen, aber ich glaube, damit kann man auch bestimmte Zahlen wie 10001 noch schneller abarbeiten, da ja gar nicht erst geprüft wird, ob die 900 abgezogen werden kann oder so. _________________ Martin Wolter
--
Apple rocks the planet! |
|
Nach oben |
|
 |
Skeeve •---->


Anmeldedatum: 20.04.2006 Beiträge: 1067
|
Verfasst am: 28.02.2008 - 19:04 Titel: |
|
|
Hier mal mit Erläuterungen:
Zitat: | arab2rom(1998, false)
on arab2rom(zahl, lower)
-- legen den "Zeichensatz" fest
if lower then
set rom_chr to characters of "ivxlcdm"
else
set rom_chr to characters of "IVXLCDM"
end if
-- Definiere "Muster" für die Ziffern 1-9
-- item of ZIFFER liefert das Muster
-- Das gibt an, welches römische Zeichen zu nehmen ist
-- 0= das aktuelle
-- 1= das nächste (also rechts davon)
-- 2= das übernächste
set rom_pat to {"0", "00", "000", "01", "1", "10", "100", "1000", "02"}
-- römische Zahl initialisieren
set rom to ""
-- 1000 ist die größte römische Zahl, wenn wir nicht
-- mit "Strichen" arbeiten wollen oder können.
-- 4000 wird also zu MMMM
set d to 1000
-- Ermittle wieviele 1000er vorkommen
set f to zahl div d
-- und merk Dir den Rest, also 1998 -> 998
set zahl to zahl - f * d
-- Einfache Schleife um soviele Ms hintereinander
-- zu hängen, bis wir genug haben
(* alt
repeat while f > 0
set rom to rom & item 7 of rom_chr
set f to f - 1
end repeat
*)
-- neu
set rom_zif to item 7 of rom_chr
repeat f times
set rom to rom & rom_zif
end repeat
-- alles kleiner 1000 also den rest) abarbeiten
-- Grundzeichen festlegen.
-- wir starten also mit "C"
set i to 5
repeat while d > 1
-- damit wird die Stelle um eins nach rechts
-- verschoben.
-- Wir arbeiten also erst die 100er ab,
-- dann die 10er und zuletzt die 1er
set d to d div 10
-- hier wieder die Ziffer holen wie
set f to zahl div d
-- wenn es eine Ziffer von 0-9 ist
if f > 0 then
-- ermittle den Rest
set zahl to zahl - f * d
-- und hole Dir das Muster
-- Arbeite jedes Zeichen des Musters ab
repeat with o in every character of item f of rom_pat
-- hänge einfach das Grundzeichen
-- (item i) hinten an. Es wird
-- zum Grundzeichen noch der Offset (o)
-- addiert. Der ist 0, 1 oder 2
set rom to rom & item (i + o) of rom_chr
end repeat
end if
-- Grundzeichen verschieben
set i to i - 2
end repeat
-- das war's
return rom
end arab2rom |
Ein Beispiellauf:
Code: |
rom_chr:I, V, X, L, C, D, M
rom_pat:0, 00, 000, 01, 1, 10, 100, 1000, 02
rom:
d:1000
f:1
zahl:998
rom_zif:M
repeat:1
rom:M
i:5
repeat:1000
d:100
f:9
i:5
zahl:98
o:0
rom:MC
o:2
rom:MCM
i:3
repeat:100
d:10
f:9
i:3
zahl:8
o:0
rom:MCMX
o:2
rom:MCMXC
i:1
repeat:10
d:1
f:8
i:1
zahl:0
o:1
rom:MCMXCV
o:0
rom:MCMXCVI
o:0
rom:MCMXCVII
o:0
rom:MCMXCVIII
i:-1
|
_________________ "All problems are solved in slightly less than half an hour" (Chumbawamba, "Hey Hey We're The Junkies")
Zuletzt bearbeitet von Skeeve am 28.02.2008 - 19:25, insgesamt einmal bearbeitet |
|
Nach oben |
|
 |
Skeeve •---->


Anmeldedatum: 20.04.2006 Beiträge: 1067
|
Verfasst am: 28.02.2008 - 19:20 Titel: |
|
|
Du hast eine if Abfrage zuviel.
Hier aber mal 2 überarbeitete Varianten Deines Handlers. Teste doch mal unter gleichen Bedingungen.
Variante 1 mit zerissenen Listen hat Folgendes geschrieben: | arab2rom(1998)
on arab2rom(zahl)
set romzahl to ""
set romliste to {"M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I"}
set romwerte to {1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1}
set i to 1
repeat with zeichen in romliste
set wert to item i of romwerte
repeat until zahl < wert
set romzahl to romzahl & zeichen
set zahl to zahl - wert
end repeat
set i to i + 1
end repeat
return romzahl
end arab2rom
|
Variante 2 mit tupeln hat Folgendes geschrieben: | arab2rom(1998)
on arab2rom(zahl)
set romzahl to ""
set romliste to {{"M", 1000}, {"CM", 900}, {"D", 500}, {"CD", 400}, {"C", 100}, {"XC", 90}, {"L", 50}, {"XL", 40}, {"X", 10}, {"IX", 9}, {"V", 5}, {"IV", 4}, {"I", 1}}
repeat with tupel in romliste
set {zeichen, wert} to tupel
repeat until zahl < wert
set romzahl to romzahl & zeichen
set zahl to zahl - wert
end repeat
end repeat
return romzahl
end arab2rom
|
_________________ "All problems are solved in slightly less than half an hour" (Chumbawamba, "Hey Hey We're The Junkies") |
|
Nach oben |
|
 |
jiuer7845 •---->

Anmeldedatum: 06.04.2021 Beiträge: 521
|
|
Nach oben |
|
 |
|
|
Du kannst keine Beiträge in dieses Forum schreiben. Du kannst auf Beiträge in diesem Forum nicht antworten. Du kannst deine Beiträge in diesem Forum nicht bearbeiten. Du kannst deine Beiträge in diesem Forum nicht löschen. Du kannst an Umfragen in diesem Forum nicht mitmachen.
|
Powered by phpBB © 2001, 2002 phpBB Group Deutsche Übersetzung von phpBB.de
|
|
|