Bergervei/Prozeduren mit Zeichenketten

Aus ProgrammingWiki

Wiki-Quelltext dieser Seite.

<language>Scheme</language>
<code id="50680af975718" hidden>
;-- M. Hielscher / Chr. Wagenknecht --
(define random-maker
  (let* ((multiplier 48271)
         (modulus 2147483647)
         (apply-congruence
          (lambda (current-seed)
            (let ((candidate (modulo (* current-seed multiplier) modulus)))
              (if (zero? candidate)
                  modulus
                  candidate))))
         (coerce
          (lambda (proposed-seed)
            (if (integer? proposed-seed)
                (- modulus (modulo proposed-seed modulus)) 19880214))))
  (lambda (initial-seed)
    (let ((seed (coerce initial-seed)))
      (lambda args
        (cond ((null? args)
               (set! seed (apply-congruence seed))
               (/ (- modulus seed) modulus))
              ((null? (cdr args))
               (let* ((proposed-top
                       (ceiling (abs (car args))))
                      (exact-top
                       (if (inexact? proposed-top)
                           (inexact->exact proposed-top)
                           proposed-top))
                      (top
                       (if (zero? exact-top)
                           1
                           exact-top)))
                 (set! seed (apply-congruence seed))
                 (inexact->exact (floor (* top (/ seed modulus))))))
              ((eq? (cadr args) 'reset)
               (set! seed (coerce (car args))))
              (else
               (display "random: unrecognized message")
               (newline))))))))

(require-library 'sisc/libs/srfi/srfi-19)
(import srfi-19)

(define random (random-maker (time-nanosecond (current-time))))
</code>

== Weitere Selektoren für Zeichenketten ==

In Anlehnung an die Selektoren <tt>car</tt> / <tt>cdr</tt> für Listen sollen zunächst analoge Selektoren für Zeichenketten entwickelt werden. Dabei ist genau auf deren Definitions- und Wertebereich zu achten. Man spricht in diesem Zusammenhang von der ''Signatur einer Prozedur'':

'''Beispiel:'''

<blockquote>
<tt><b>string-car:</b></tt> <math>string \longmapsto char</math>
</blockquote>

<table border="1" cellspacing="1" cellpadding="4">
<tr>
<td width="400" align="center" valign="top">[[Bild:String_car.GIF]]</td>
<td width="900" align="left" valign="top">
<code id="5066bb1a26893">
(define string-car
  (lambda (zk)
    (string-ref zk 0)))
</code>

<run id="5066bb1a26a6d">(string-car "Informatik")</run>
</td>
</tr>
<tr>
<td width="400" align="center" valign="top">[[Bild:String_cdr.GIF]]</td>
<td width="900" align="left" valign="top">
<code id="5066bb1a26900">
(define string-cdr
  (lambda (zk)
    (substring zk 1 (string-length zk))))
</code>

<run id="5066bb1a26ace">(string-cdr "Informatik")</run>
</td>
</tr>
<tr>
<td width="400" align="center" valign="top">[[Bild:String_last.GIF]]</td>
<td width="900" align="left" valign="top">
<code id="5066bb1a26963">
(define string-last
  (lambda (zk)
   (string-ref zk (- (string-length zk) 1))))
</code>

<run id="5066bb1a26b2c">(string-last "Informatik")</run>
</td>
</tr>
</table>

== Generierung von Benutzernamen und Passwörtern ==

<table border="0" cellspacing="1" cellpadding="0">
<tr>
<td align="left" valign="top">
Der Administrator eines Computernetzwerkes möchte die Festlegung von Benutzernamen und Passwörtern für eine größere Anzahl von Benutzern automatisieren. Dazu legt er fest:
<ul>
<li>
Der Benutzername setzt sich aus den ersten drei Buchstaben des Vornamens und dem kompletten Nachnamen zusammen. Diese Zeichenkette wird grundsätzlich klein geschrieben.
</li>
<li>
Das Passwort zur Erstanmeldung soll aus dem ersten Buchstaben des Vornamens und dem letzten Buchstaben des Nachnamens bestehen. Beide Zeichen sollen Kleinbuchstaben sein und den Zahlenwert einschließen, der der Summe aller Zeichen im Vor- und Nachnamen entspricht.
</li> 
</ul>
</td>
<td align="center" valign="center">[[Bild:Anmeldung.gif]]
Beispiel einer Netzwerkanmeldung
</td>
</tr>
</table>

'''Beispiel:'''

 > (benutzername "Beatrix "Berger")
 --> "beaberger"
 > (passwort "Beatrix "Berger")
 --> "b13r"

Implementieren Sie beide Prozeduren.

'''Hinweis:'''

Im ''ProgrammingWiki'' können folgende Scheme-Prozeduren genutzt werden:

 (string-downcase <zk>) ; ... Konvertierung einer Zeichenkette in Kleinbuchstaben
 (string-upcase <zk>)   ; ... Konvertierung einer Zeichenkette in Großbuchstaben

<code id="5066f3df4b6f7">
(define benutzername
  (lambda (vorname nachname)
    (string-downcase
      (string-append (substring vorname 0 3) nachname))))
</code>

<run id="5066f3df4b9fd">
(benutzername "Beatrix" "Berger")
</run>

<code id="5066f3df4b7ad">
(define passwort
  (lambda (vorname nachname)
    (string-downcase
      (string-append (string (string-car vorname))
                     (number->string (+ (string-length vorname) (string-length nachname)))
                     (string (string-last nachname))))))
</code>

<run id="5066f3df4ba9e">
(passwort "Beatrix" "Berger")
</run>

<code id="5066f3df4b85e">
(define login
  (lambda (vorname nachname)
    (cons (benutzername vorname nachname) (passwort vorname nachname))))
</code>

<run id="5066f3df4bb3f">
(login "Beatrix" "Berger")
</run>

== Kfz-Kennzeichen ==

=== Das persönliche Kfz-Kennzeichen ===

[[Bild:Kennzeichen_Deutschland.jpg|miniatur|hochkant=1.5|Aktuelles deutsches Kfz-Kennzeichen aus dem Landkreis Rastatt (Baden-Württemberg)]]

Viele Autofahrer legen großen Wert auf ein ganz individuelles polizeiliches Kennzeichen an ihrem Fahrzeug. Häufig soll es die Anfangsbuchstaben des Vor- und Nachnamens sowie den Geburtstag und den Geburtsmonat beinhalten.<br />

Schreiben Sie eine Prozedur, die die persönliche Daten entgegennimmt und das gewünschte Kennzeichen als Zeichenkette für den Landkreis Görlitz in Großbuchstaben zurückgibt.

'''Beispiel:'''
 
 > (kennzeichen "Romy" "Berger" '(14 02 1988))
 --> "GR-RB 142"

<code id="5066f4c8e167a">
(define kennzeichen
  (lambda (vorname nachname datum)
    (string-upcase
      (string-append "GR-"
                     (string (string-car vorname))
                     (string (string-car nachname))
                     " "
                     (number->string (car datum))
                     (number->string (cadr datum))))))
</code>

<run id="5066f4c8e1749">
(kennzeichen "Romy" "Berger" '(14 02 1988))
</run>

=== Das zufällige Kfz-Kennzeichen ===

Persönliche Wunsch-Kennzeichen sind leider oft vergeben. Nun muss das Kennzeichen aus zufällig gewählten Buchstaben und Zahlen generiert werden.
Wir experimentieren deshalb mit Zufallszahlen. Dazu nutzen wir die einstellige Prozedur <tt>random</tt>:

<run id="5067696a5b9a3">
(random 100)
</run>

Dabei stellen wir fest: <tt>(random &lt;max&gt;)</tt> gibt eine ganze Zufallszahl <math>z</math> zurück mit <math>0 \le z < max</math>.<br />
Mit der nachfolgenden ''nullstelligen Prozedur'' <tt>zufallszahl</tt> lässt sich also eine zufällige ganze Zahl <math>z</math> mit <math>1 \le z \le 10</math> erzeugen:

<code id="5067696a5b6eb">
(define zufallszahl
  (lambda ()
    (+ 1 (random 10))))
</code>

<run id="5067696a5bbcf">
(zufallszahl)
</run>

Nun können wir auch zufällige Kfz-Kennzeichen generieren. Dazu vereinbaren wir:
<ul>
<li>
Dem Landkreiskürzel "GR" sollen (zunächst) immer <u>zwei</u> zufällig gewählte Großbuchstaben folgen.<br />
Hier sind im Gegensatz zu realen Kennzeichen alle Buchstabenkombinationen zulässig.
</li>
<li>
Die darauf folgende Zufallszahl <math>z</math> muss im Intervall <math>1 \le z \le 9999</math> liegen.
</li>
</ul>
Erstellen Sie die nullstellige Prozedur <tt>zufallskennzeichen</tt>, die für den Landkreis Görlitz zufällige Kfz-Kennzeichen erzeugt. Nutzen Sie dazu die Variable <tt>alphabet</tt>, mit der eine Zeichenkette aus allen Großbuchstaben definiert wird:

<code id="50683c8821a7b">
(define alphabet "ABCDEFGHIJKLMNOPQRSTUVWXYZ")

(define zufallskennzeichen
  (lambda ()
    (string-append "GR-"
                   (string (string-ref alphabet (random (- (string-length alphabet) 1))))
                   (string (string-ref alphabet (random (- (string-length alphabet) 1))))
                   " "
                   (number->string (+ 1 (random 9999))))))
</code> 

<run id="50683c8821b7f">
(zufallskennzeichen)
</run>

=== Zum Weiterarbeiten: Das allgemeine zufällige Kfz-Kennzeichen ===

Es ist durchaus zulässig, dass dem Landkreiskürzel nur ein Buchstabe folgt.<br />
Verallgemeinern Sie die Prozedur <tt>zufallskennzeichen</tt> in der Form, dass ein <u>oder</u> zwei Buchstaben hinter einem <u>beliebigen</u> Landkreiskürzel auftreten können.<br />

Zur [[Bergervei/Das allgemeine zufällige Kfz-Kennzeichen|Problemlösung]].