From 8deee553623a85534efa66376b0d81f3c516dd46 Mon Sep 17 00:00:00 2001 From: Martin Thoma Date: Mon, 13 Aug 2012 22:16:50 +0200 Subject: [PATCH] added another document example --- ...ngsreisender-in-Deutschland-Alle-Routen.py | 107 ++++++++++ ...sender-in-Deutschland-Nearest-Insertion.py | 59 +++++ ...ndlungsreisender-in-Deutschland-analyse.py | 72 +++++++ .../Handlungsreisender-in-Deutschland.tex | 201 ++++++++++++++++++ documents/mathe-handlungsreisender/Makefile | 6 + .../mathe-handlungsreisender/slashbox.sty | 77 +++++++ 6 files changed, 522 insertions(+) create mode 100644 documents/mathe-handlungsreisender/Handlungsreisender-in-Deutschland-Alle-Routen.py create mode 100644 documents/mathe-handlungsreisender/Handlungsreisender-in-Deutschland-Nearest-Insertion.py create mode 100644 documents/mathe-handlungsreisender/Handlungsreisender-in-Deutschland-analyse.py create mode 100644 documents/mathe-handlungsreisender/Handlungsreisender-in-Deutschland.tex create mode 100644 documents/mathe-handlungsreisender/Makefile create mode 100644 documents/mathe-handlungsreisender/slashbox.sty diff --git a/documents/mathe-handlungsreisender/Handlungsreisender-in-Deutschland-Alle-Routen.py b/documents/mathe-handlungsreisender/Handlungsreisender-in-Deutschland-Alle-Routen.py new file mode 100644 index 0000000..11d920f --- /dev/null +++ b/documents/mathe-handlungsreisender/Handlungsreisender-in-Deutschland-Alle-Routen.py @@ -0,0 +1,107 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +""" Dieses Script berechnet die Länge aller möglichen Routen und speichert sie + in "Entfernungen.txt". + Am Ende wird noch die optimale Route ausgegeben. + + Benötigte Rechenzeit: ca. 50s """ + +from copy import deepcopy + +# http://blog.bjrn.se/2008/04/lexicographic-permutations-using.html +def next_permutation(seq, pred=cmp): + """Like C++ std::next_permutation() but implemented as + generator. Yields copies of seq.""" + def reverse(seq, start, end): + # seq = seq[:start] + reversed(seq[start:end]) + \ + # seq[end:] + end -= 1 + if end <= start: + return + while True: + seq[start], seq[end] = seq[end], seq[start] + if start == end or start+1 == end: + return + start += 1 + end -= 1 + if not seq: + raise StopIteration + try: + seq[0] + except TypeError: + raise TypeError("seq must allow random access.") + first = 0 + last = len(seq) + seq = seq[:] + # Yield input sequence as the STL version is often + # used inside do {} while. + yield seq + if last == 1: + raise StopIteration + while True: + next = last - 1 + while True: + # Step 1. + next1 = next + next -= 1 + if pred(seq[next], seq[next1]) < 0: + # Step 2. + mid = last - 1 + while not (pred(seq[next], seq[mid]) < 0): + mid -= 1 + seq[next], seq[mid] = seq[mid], seq[next] + # Step 3. + reverse(seq, next1, last) + # Change to yield references to get rid of + # (at worst) |seq|! copy operations. + yield seq[:] + break + if next == first: + raise StopIteration + raise StopIteration + +def Strecke_der_Route(Entfernungen, route): + """ Bestimmt die länge der Route und gibt diese als int zurück """ + Entfernung = 0 + for step, index in enumerate(route): + index2 = route[(step+1)%len(Entfernungen)] + Entfernung += Entfernungen[index][index2] # von index nach index2 + return Entfernung + +def optimal_solution_with_brute_force(Entfernungen): + """ Findet die optimale Lösung, indem alle Routen durchgegangen werden. + Zurückgegeben wird eine Liste mit den Indizes """ + liste = [i for i in xrange(0, len(Entfernungen))] + min_Entfernung_Route = [i for i in xrange(0, len(Entfernungen))] + min_Entfernung = Strecke_der_Route(Entfernungen, min_Entfernung_Route) + f = open('/home/moose/Entfernungen.txt', 'w') + for route in next_permutation(liste): + entfernung_tmp = Strecke_der_Route(Entfernungen, route) + f.write(str(entfernung_tmp) + "\n") + if entfernung_tmp < min_Entfernung: + min_Entfernung = entfernung_tmp + min_Entfernung_Route = deepcopy(route) + f.close() + return min_Entfernung_Route + +Stadtliste = ['Berlin', 'Hamburg', 'München', 'Köln', 'Frankfurt a. M.', + 'Stuttgart', 'Düsseldorf', 'Dortmund', 'Essen', 'Bremen'] +Entfernungen = [] +Entfernungen.append([ 0, 288, 585, 575, 547, 633, 559, 494, 531, 392]) +Entfernungen.append([289, 0, 775, 426, 493, 655, 400, 344, 365, 122]) +Entfernungen.append([589, 775, 0, 577, 398, 220, 612, 604, 634, 748]) +Entfernungen.append([579, 426, 576, 0, 193, 369, 42, 95, 73, 320]) +Entfernungen.append([552, 492, 393, 193, 0, 210, 229, 219, 251, 445]) +Entfernungen.append([637, 667, 231, 369, 203, 0, 404, 417, 426, 642]) +Entfernungen.append([563, 408, 611, 38, 228, 404, 0, 71, 37, 302]) +Entfernungen.append([498, 346, 605, 95, 221, 418, 69, 0, 36, 240]) +Entfernungen.append([536, 374, 634, 74, 252, 427, 35, 37, 0, 267]) +Entfernungen.append([397, 123, 748, 315, 441, 638, 289, 233, 254, 0]) + +print("Berechnung aller Routen wurde begonnen.") +route = optimal_solution_with_brute_force(Entfernungen) +print("Berechnung aller Routen wurde abgeschlossen.") +print("Länge der optimalen Route: ", Strecke_der_Route(Entfernungen, route)) +for index in route: + print(Stadtliste[index]) diff --git a/documents/mathe-handlungsreisender/Handlungsreisender-in-Deutschland-Nearest-Insertion.py b/documents/mathe-handlungsreisender/Handlungsreisender-in-Deutschland-Nearest-Insertion.py new file mode 100644 index 0000000..1628d22 --- /dev/null +++ b/documents/mathe-handlungsreisender/Handlungsreisender-in-Deutschland-Nearest-Insertion.py @@ -0,0 +1,59 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +from copy import deepcopy + +def compute_length(Entfernungen, route): + """ Berechnet die Länge der Route und gibt diesen Integer zurück. """ + entfernung = 0 + for i in xrange(0, len(route)-1): + entfernung += Entfernungen[route[i]][route[i+1]] + return entfernung + +def nearest_insertion(Entfernungen): + """ Entfernungen: Entfernungen[x][y] gibt die Länge der Strecke von x nach + y als integer an. + return: route als Liste, z.B. [0,3,4,1,2] + Es wird immer mit der Stadt 0 begonnen. """ + route = [0] + cities = len(Entfernungen) + maxEntfernung = max([item for sublist in Entfernungen for item in sublist]) + aktuelleCity = 0 + Entfernungen_read = deepcopy(Entfernungen) + for i in xrange(0, cities): + for sublist in Entfernungen: + sublist[aktuelleCity] = maxEntfernung + 1 + aktuelleCity = Entfernungen[aktuelleCity].index( min(Entfernungen[aktuelleCity]) ) + minInsert = None + routenLaenge = len(route)*(maxEntfernung+1) + for insertIndex in xrange(0, len(route) ): + route_tmp = deepcopy(route) + route_tmp.insert(insertIndex, aktuelleCity) + if compute_length(Entfernungen_read, route_tmp) < routenLaenge: + routenLaenge = compute_length(Entfernungen_read, route_tmp) + minInsert = insertIndex + route.insert(minInsert, aktuelleCity) + routenLaenge+= Entfernungen[route[-1]][aktuelleCity] + + #Drehen der Route, sodass Berlin am Anfang und am Ende steht + route = route[route.index(0)+1:] + route[0:route.index(0)+1] + + print("Routenlänge: %i" % compute_length(Entfernungen_read, route)) + return route + +Entfernungen = [] +Entfernungen.append([ 0, 288, 585, 575, 547, 633, 559, 494, 531, 392]) +Entfernungen.append([289, 0, 775, 426, 493, 655, 400, 344, 365, 122]) +Entfernungen.append([589, 775, 0, 577, 398, 220, 612, 604, 634, 748]) +Entfernungen.append([579, 426, 576, 0, 193, 369, 42, 95, 73, 320]) +Entfernungen.append([552, 492, 393, 193, 0, 210, 229, 219, 251, 445]) +Entfernungen.append([637, 667, 231, 369, 203, 0, 404, 417, 426, 642]) +Entfernungen.append([563, 408, 611, 38, 228, 404, 0, 71, 37, 302]) +Entfernungen.append([498, 346, 605, 95, 221, 418, 69, 0, 36, 240]) +Entfernungen.append([536, 374, 634, 74, 252, 427, 35, 37, 0, 267]) +Entfernungen.append([397, 123, 748, 315, 441, 638, 289, 233, 254, 0]) +Stadtliste = ['Berlin', 'Hamburg', 'München', 'Köln', 'Frankfurt a. M.', + 'Stuttgart', 'Düsseldorf', 'Dortmund', 'Essen', 'Bremen'] + +for city in nearest_insertion(Entfernungen): + print("%s" % Stadtliste[city]) diff --git a/documents/mathe-handlungsreisender/Handlungsreisender-in-Deutschland-analyse.py b/documents/mathe-handlungsreisender/Handlungsreisender-in-Deutschland-analyse.py new file mode 100644 index 0000000..a190edf --- /dev/null +++ b/documents/mathe-handlungsreisender/Handlungsreisender-in-Deutschland-analyse.py @@ -0,0 +1,72 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +""" Dieses Script analysiert die Verteilung der Längen der Routen. Diese müssen + durch "Entfernungen.txt" gegeben sein. + + """ + +print("Beginne alle Routen zu lesen.") +f = open('/home/moose/mathe/Entfernungen.txt', 'r') +lines = f.readlines() +f.close() +print("Alle Routen wurden eingelesen.") + +number = length = 0 +minimum= int(lines[0]) +maximum= int(lines[0]) +liste = [] +dict_entfernungen = {} +for line in lines: + line = int(line) + if line in dict_entfernungen: + dict_entfernungen[line] += 1 + else: + dict_entfernungen[line] = 1 + liste.append(line) + number += 1 + length += line + if line < minimum: + minimum = line + if line > maximum: + maximum = line +print("Minimum: %i" % minimum) +print("Maximum: %i" % maximum) +print("Durchschnitt: %i" % (length/number)) +print("Anzahl der Routen: %i" % number) + +less_than2069 = 0.0 +for length, count in dict_entfernungen.items(): + if length <= 2068: + less_than2069 += count + +print("maximale Abweichung von 5%%: %f %% aller Strecken" % (less_than2069/number*100)) + +EntfernungsSet = set(liste) +print("Anzahl der verschiedenen Streckenlängen: %i" % len(dict_entfernungen)) + +import math, pylab + +x_list = [] +y_list = [] +for x, y in dict_entfernungen.items(): + y_list.append(y) + x_list.append(x) + +pylab.xlabel("Streckenlange in km") +pylab.ylabel("Anzahl der Routen") +pylab.plot(x_list, y_list, 'b') + +# Einzeichnen des Durchschnitts: +y_max = max(y_list) +x_list = [] +y_list = [] +y_list.append(0) +x_list.append((length/number)) +y_list.append(y_max) +x_list.append((length/number)) +pylab.plot(x_list, y_list, 'r') + +pylab.savefig('Fig1.png') + +pylab.show() diff --git a/documents/mathe-handlungsreisender/Handlungsreisender-in-Deutschland.tex b/documents/mathe-handlungsreisender/Handlungsreisender-in-Deutschland.tex new file mode 100644 index 0000000..c83d76f --- /dev/null +++ b/documents/mathe-handlungsreisender/Handlungsreisender-in-Deutschland.tex @@ -0,0 +1,201 @@ +\documentclass[a4paper,9pt]{scrartcl} +\usepackage[ngerman]{babel} +\usepackage[utf8]{inputenc} +\usepackage{amssymb,amsmath} +\usepackage{geometry} +\usepackage{graphicx} +\usepackage{hyperref} +\usepackage{listings} +\usepackage{color} + +\usepackage{slashbox} + +\definecolor{gray}{gray}{0.5} + +\lstset{ +language=Python, % the language of the code +basicstyle=\footnotesize, % the size of the fonts that are used for the code +keywordstyle=\color{blue}, +stringstyle=\color{red}, +commentstyle=\color{gray}\slshape, +emph={class, pass, in, for, while, if, is, elif, else, not, and, or, def, print, exec, break, continue, return}, +emphstyle=\color{black}\bfseries, +emph={[2]True, False, None, self}, +emph={[3]from, import, as}, +emphstyle=[3]\color{blue}, +morecomment=[s]{"""}{"""}, +rulesepcolor=\color{blue}, +otherkeywords={1, 2, 3, 4, 5, 6, 7, 8 ,9 , 0, -, =, +, [, ], (, ), \{, \}, :, *, !}, +numbers=left, % where to put the line-numbers +numberstyle=\footnotesize, % the size of the fonts that are used for the line-numbers +stepnumber=1, % the step between two line-numbers. If it's 1, each line + % will be numbered +numbersep=5pt, % how far the line-numbers are from the code +showspaces=false, % show spaces adding particular underscores +showstringspaces=false, % underline spaces within strings +showtabs=false, % show tabs within strings adding particular underscores +tabsize=2, % sets default tabsize to 2 spaces +captionpos=b, % sets the caption-position to bottom +breaklines=true, % sets automatic line breaking +breakatwhitespace=false, % sets if automatic breaks should only happen at whitespace +title=\lstname, % show the filename of files included with \lstinputlisting; + % also try caption instead of title +escapeinside={\%*}{*)}, % if you want to add a comment within your code +morekeywords={*,...}, % if you want to add more keywords to the set +literate=% +{Ö}{{\"O}}1 +{Ä}{{\"A}}1 +{Ü}{{\"U}}1 +{ß}{{\ss}}2 +{ü}{{\"u}}1 +{ä}{{\"a}}1 +{ö}{{\"o}}1 +} + +\geometry{a4paper,left=18mm,right=18mm, top=1cm, bottom=2cm} + +\setcounter{secnumdepth}{2} +\setcounter{tocdepth}{2} + +\shorthandon{"} +\hypersetup{ + pdftitle={Handlungsreisender in Deutschland}, + pdfsubject={Aufgabe}, + pdfauthor={Martin Thoma}, + pdfkeywords={Aufgabe, Mathematik, Lösung}} +\shorthandoff{"} + +\begin{document} + \title{Handlungsreisender in Deutschland} + \author{Martin Thoma} + + + \setcounter{section}{1} + \section*{Aufgabenstellung} + Ein Handlungsreisender will seine Produkte in den zehn größten Städten + Deutschlands verkaufen. Er startet in Berlin und will seine Reise dort + beenden. + + Die zehn einwohnerreichsten Städte Deutschlands sind Berlin, Hamburg, + München, Köln, Frankfurt am Main, Stuttgart, Düsseldorf, Dortmund, Essen + und Bremen. \\ + Folgende Tabelle gibt die Entfernung zwischen den Städten für eine Autoreise + wieder\footnote{Mit maps.google.com ermittelte Werte. Es wurde immer auf ganze Kilometer gerundet.}: + + \begin{tabular}[hc]{|l|c|c|c|c|c|c|c|c|c|c|} + \hline + \backslashbox{von}{nach} & \rotatebox{90}{Berlin} & \rotatebox{90}{Hamburg} & \rotatebox{90}{München} & \rotatebox{90}{Köln} & \rotatebox{90}{Frankfurt am Main} & \rotatebox{90}{Stuttgart} & \rotatebox{90}{Düsseldorf} & \rotatebox{90}{Dortmund} & \rotatebox{90}{Essen} & \rotatebox{90}{Bremen} \\ + \hline\hline + Berlin & 0 & 288 & 585 & 575 & 547 & 633 & 559 & 494 & 531 & 392 \\ + Hamburg & 289 & 0 & 775 & 426 & 493 & 655 & 400 & 344 & 365 & 122 \\ + München & 589 & 775 & 0 & 577 & 398 & 220 & 612 & 604 & 634 & 748 \\ + Köln & 579 & 426 & 576 & 0 & 193 & 369 & 42 & 95 & 73 & 320 \\ + Frankfurt a. M. & 552 & 492 & 393 & 193 & 0 & 210 & 229 & 219 & 251 & 445 \\ + Stuttgart & 637 & 667 & 231 & 369 & 203 & 0 & 404 & 417 & 426 & 642 \\ + Düsseldorf& 563 & 408 & 611 & 38 & 228 & 404 & 0 & 71 & 37 & 302 \\ + Dortmund & 498 & 346 & 605 & 95 & 221 & 418 & 69 & 0 & 36 & 240 \\ + Essen & 536 & 374 & 634 & 74 & 252 & 427 & 35 & 37 & 0 & 267 \\ + Bremen & 397 & 123 & 748 & 315 & 441 & 638 & 289 & 233 & 254 & 0 \\ + \hline + \end{tabular}\\ + \\ + Welche Route sollte er wählen? + + \subsection{Größenordnung des Problems} + Es gibt $9! = 9 \cdot 8 \cdot 7 \cdot 6 \cdot 5 \cdot 4 \cdot 3 \cdot 2 \cdot 1 = 362.880$ mögliche Routen, + da der Handlungsreisende in Berlin startet und 9 Möglichkeiten für die erste + Stadt hat, 8 für die zweite, usw.\\ + Allgemein kann man sagen, dass bei $n$ Städten insgesamt $(n-1)!$ mögliche + Routen bestehen, da die Wahl des Startpunktes egal ist. \\ + Falls das Problem symmetrisch wäre, also die Strecke von Berlin nach + München genauso lang wie die von München nach Berlin wäre, könnte man die + Anzahl der Routen auf $\frac{(n-1)!}{2}$ reduzieren. Allerdings ist das + Problem offensichtlich asymmetrisch (siehe München $\rightarrow$ Berlin und + München $\leftarrow$ Berlin) + + Die Tabelle \ref{tab:functionGrowth} macht deutlich, wie schnell so etwas + wächst. + \begin{table}[hc] + \centering + \begin{tabular}[hc]{|l|r|r|r|r|r|r|} + \hline + n & $1$ & $log(n)$ & $n \cdot log(n)$ & $n^2$ & $n^3$ & $n!$ \\ + \hline\hline + 1 & 1 & 0 & 0 & 1 & 1 & 1 \\ + 2 & 1 & 0,30 & 0,60 & 4 & 8 & 2 \\ + 3 & 1 & 0,48 & 1,43 & 9 & 27 & 6 \\ + 4 & 1 & 0,60 & 2,41 & 16 & 64 & 24 \\ + 5 & 1 & 0,70 & 3,49 & 25 & 125 & 120 \\ + 6 & 1 & 0,78 & 4,67 & 36 & 216 & 720 \\ + 7 & 1 & 0,85 & 5,92 & 49 & 343 & 5.040 \\ + 8 & 1 & 0,90 & 8,13 & 64 & 512 & 40.320\\ + 9 & 1 & 0,95 & 8,59 & 81 & 729 & 362.880\\ + 10 & 1 & 1,00 & 10,00 & 100 & 1.000 & 3.628.800\\ + 20 & 1 & 1,30 & 26,02 & 400 & 8.000 & $2,42 \cdot 10^{18}$ \\ + \hline + \end{tabular} + \caption{Wachstum verschiedener Funktionen} + \label{tab:functionGrowth} + \end{table} + \newpage + \subsection{Intuitive Lösung} + Wenn man die Städte so auf der Karte sieht sollte man einfach mal die Route + suchen, von der man denkt sie wäre gut. \\ + \begin{center} + %\includegraphics{Germany_location_map.png} + \end{center} + Ich habe mir folgende ausgesucht:\\ + \begin{center} + %\includegraphics{Germany_location_map-intuitiv.png} + \end{center} + Das ist die Route Berlin $\rightarrow$ München $\rightarrow$ Stuttgart + $\rightarrow$ Frankfurt a. M. $\rightarrow$ Köln $\rightarrow$ Düsseldorf + $\rightarrow$ Essen $\rightarrow$ Dortmund $\rightarrow$ Bremen + $\rightarrow$ Hamburg $\rightarrow$ Berlin. + Diese Route ist 1969 km lang. + + \newpage + \subsection{Optimale Lösung} + \subsubsection{Alle Routen durchgehen} + Die primitivste und langsamste Methode zum Finden der optimalen Lösung ist + einfach alle möglichen Routen durch zu gehen. Dieser Algorithmus ist, was + die Ausführungszeit angeht, in $\mathcal{O}(n!)$. Wie schnell diese wächst + sollte mit Tabelle \ref{tab:functionGrowth} klar geworden sein.\\ + Dieser Ansatz ist also nur für sehr kleine Instanzen des Problems geeignet.\\ + \\ + Eine Auswertung aller Stecken hat folgende Ergebnisse geliefert: \\ + 1969 km bzw. die von mir intuitiv gefundene Strecke ist eine von 10 optimalen Lösungen.\\ + Die längste Route ist 4.913 km lang.\\ + Es gibt 3.628.800 Routen, jedoch nur 2.597 verschiedene Streckenlängen. Die + durchschnittliche Streckenlänge beträgt 3.838 km und wurde rot eingezeichnet, + die maximale 4.913 km.\\ + Die Verteilung der Streckenlängen sieht wie folgt aus:\\ + %\includegraphics{Kurve.png} + \\ + Würde man eine maximale Abweichung von $5\%$ akzeptieren, wären nur $0,002\%$ + aller Routen akzeptabel. Durch eine zufällig gewählte Strecke wird man also + kaum ein gutes Ergebnis erziehlen + \subsection{Heuristiken} + Eine Heuristik ist in diesem Zusammenhang ein vereinfachtes Verfahren, das + keine optimale Lösung liefert, aber eine akzeptable Näherung daran. Dafür + ist die Heuristik deutlich schneller.\\ + \subsubsection{Nächster Nachbar} + Eine mögliche Heurisik ist das auswählen der Stadt, die am nächsten zur + aktuellen Stadt liegt. Mit diesem Verfahren erhält man bei der gegebenen + Städtekonstellation eine Route der Länge 2.162 km. Das sind 193 km oder + $9,8\%$ mehr als die optimale Lösung benötigt. + + \subsubsection{Nächster Nachbar - Dynamisch Einfügen} + Die Methode des nächsten Nachbars kann verbessert werden, indem der Nachbar + nicht einfach am Ende in die Route eingefügt wird, sondern an die Stelle, an + der die resultierende Route am kleinsten wäre. Damit erhält man bei der + gegebenen Städtekonstellation eine optimale Route. + + \newpage + \lstinputlisting[language=Python]{Handlungsreisender-in-Deutschland-Alle-Routen.py} + \newpage + \lstinputlisting[language=Python]{Handlungsreisender-in-Deutschland-analyse.py} + \newpage + %\lstinputlisting[language=Python]{Handlungsreisender-in-Deutschland-Nearest-Neighbour.py} + \lstinputlisting[language=Python]{Handlungsreisender-in-Deutschland-Nearest-Insertion.py} +\end{document} diff --git a/documents/mathe-handlungsreisender/Makefile b/documents/mathe-handlungsreisender/Makefile new file mode 100644 index 0000000..b9a5d76 --- /dev/null +++ b/documents/mathe-handlungsreisender/Makefile @@ -0,0 +1,6 @@ +make: + pdflatex Handlungsreisender-in-Deutschland.tex -output-format=pdf + make clean + +clean: + rm -rf $(TARGET) *.class *.html *.log *.aux *.out diff --git a/documents/mathe-handlungsreisender/slashbox.sty b/documents/mathe-handlungsreisender/slashbox.sty new file mode 100644 index 0000000..1712c9e --- /dev/null +++ b/documents/mathe-handlungsreisender/slashbox.sty @@ -0,0 +1,77 @@ +% slashbox.sty by Koichi Yasuoka, May 27, 1993 +% minor modification by Toru Sato, May 31, 1993 +\typeout{slashbox style by K.Yasuoka, May 1993.}% +\newbox\@slashboxa +\newbox\@slashboxb +\newbox\@slashboxc +\newcount\@slashboxwd +\newcount\@slashboxht +\newdimen\@slashsepl +\newdimen\@slashsepr +\def\slashbox{% + \def\@slashboxpicture##1{% + \put(0,0){\line(##1,1){\@slashboxwd}}% + \put(0,\@slashboxht){\makebox(0,0)[tl]{\box\@slashboxa}}% + \put(\@slashboxwd,0){\makebox(0,0)[br]{\box\@slashboxb}}% + }% + \@slashbox +}% +\def\backslashbox{% + \def\@slashboxpicture##1{% + \put(0,\@slashboxht){\line(##1,-1){\@slashboxwd}}% + \put(0,0){\makebox(0,0)[bl]{\box\@slashboxa}}% + \put(\@slashboxwd,\@slashboxht){\makebox(0,0)[tr]{\box\@slashboxb}}% + }% + \@slashbox +}% +\def\@slashbox{\@ifnextchar [{\@@slashbox}{\@@slashbox[0pt]}} +\def\@@slashbox[#1]{\@ifnextchar [{\@@@slashbox[#1]}{\@@@slashbox[#1][c]}} +\def\@@@slashbox[#1][#2]#3#4{% +% #1: width, #2: suppression of \tabcolsep on `l', `r', or `lr' side +% #3: left item, #4: right item + \@slashsepl=\tabcolsep + \@slashsepr=\tabcolsep + \@tfor\@tempa :=#2\do{\expandafter\let + \csname @slashsep\@tempa\endcsname=\z@}% + \setbox\@slashboxa=\hbox{\strut\hskip\tabcolsep\shortstack[l]{#3}}% + \setbox\@slashboxb=\hbox{\shortstack[r]{#4}\hskip\tabcolsep\strut}% + \setbox\@slashboxa=\hbox{\raise\dp\@slashboxa\box\@slashboxa}% + \setbox\@slashboxb=\hbox{\raise\dp\@slashboxb\box\@slashboxb}% + \setbox\@slashboxc=\hbox{% + \@tempdima=\wd\@slashboxa + \advance\@tempdima by \wd\@slashboxb + \advance\@tempdima by \@slashsepl + \advance\@tempdima by \@slashsepr + \@tempdimb=#1\relax% + \ifdim\@tempdimb>\@tempdima \@tempdima=\@tempdimb\fi% + \@tempdimb=\ht\@slashboxa + \advance\@tempdimb by \dp\@slashboxa + \advance\@tempdimb by \ht\@slashboxb + \advance\@tempdimb by \dp\@slashboxb + \@tempcnta=\@tempdima + \@tempcntb=\@tempdimb + \advance\@tempcnta by \@tempcntb + \advance\@tempcnta by -1 + \divide\@tempcnta by \@tempcntb + \ifnum\@tempcnta>6 \@tempcnta=6 + \@tempdimb=0.166666666\@tempdima + \else + \ifnum\@tempcnta<1 \@tempcnta=1\fi + \@tempdima=\@tempdimb + \multiply\@tempdima by \@tempcnta + \fi% + \advance\@tempdima by -\@slashsepl + \advance\@tempdima by -\@slashsepr + \@slashboxwd=\@tempdima + \@slashboxht=\@tempdimb + \@tempcntb=\@slashsepl + \setlength{\unitlength}{1sp}% + \begin{picture}(\@slashboxwd,\@slashboxht)(\@tempcntb,0) + \advance\@tempdima by \@slashsepl + \advance\@tempdima by \@slashsepr + \@slashboxwd=\@tempdima + \@slashboxpicture{\@tempcnta} + \end{picture}% + }% + $\vcenter{\box\@slashboxc}$% +}%