If Abfragen mit einer print anweisung

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Kandalius
User
Beiträge: 3
Registriert: Freitag 28. Oktober 2016, 14:20

Moinsen,

ich habe eine Aufgabe hier, die ich einfach nicht verstehe. Bin ein absoluter Anfänger in python, sprich ihr werdet vielleicht lachen.
Ich muss einen benutzer des programms durch folgenden entscheidungsbaum lenken:
https://upload.wikimedia.org/wikipedia/ ... rn_neu.svg

theoretisch ist es ziemlich einfach, dachte ich jedenfalls. uns wurde aber ein Codegerüst vorgegeben mit einer print anweisung. sie soll die einzige sein, die wir auch nur an der stelle nutzen dürfen. habe soweit ich kann schon was reingeschrieben, verstehe es aber mit dem print nicht.

erstmal das vorgegebene gerüst:
[codebox=python file=Unbenannt.txt]print("Urheberrechtsabfrage")
print()
print("Bitte beantworten Sie alle Fragen durch Eingabe von "n" für nein und "j" für ja.")
print()

… <HIER IST EVTL. CODE ZU ERGÄNZEN>


selbstErstellt = input("Hast Du das Bild selbst erstellt? (j/n)")

… <HIER IST DER CODE ZU ERGÄNZEN>

if hochladen:
print("Bild hochladen")
else:
print("Bild darf nicht hochgeladen werden")
[/code]


nun das, was ich bis jetzt gemacht habe:
[codebox=python file=Unbenannt.txt]print("Urheberrechtsabfrage")
print()
print("Bitte beantworten Sie alle Fragen durch Eingabe von n fuer nein und j für ja.")
print()




selbstErstellt = input("Hast Du das Bild selbst erstellt? (j/n)")



if selbstErstellt== "j":
lizens = input("Willst du das Bild unter einer in der Wikipedia zulaessigen Lizens veroeffentlichen? (j/n)")
if lizens == "j":
rechte = input("Sind Bildrechte Dritter ausgeschlossen? (j/n)")
if rechte == "j":
# hochladen
else:
schrift = input("Hast du das schriftliche Einverstaendnis aller Betroffenen? (j/n)")
if schrift == "j":
# hochladen
else:
# nicht hochladen
else:
# nicht hochladen
else:
alter = input("Ist das Bild mehr als 100 Jahre alt? (j/n)")
if alter == "j":
# hochladen
else:
bekannt = input("Ist der Urheber des Bildes bekannt? (j/n)")
if bekannt == "j":
verstorben = input("Ist der Urheber vor mehr als 70 Jahren verstorben? (j/n")
if verstorben == "j":
rechte = input("Sind Bildrechte Dritter ausgeschlossen? (j/n)")
if rechte == "j":
# hochladen
else:
schrift = input("Hast du das schriftliche Einverstaendnis aller Betroffenen? (j/n)")
if schrift == "j":
# hochladen
else:
# nicht hochladen
else:
zustimmung = input("Hat der Urheber des Bides zugestimmt, das Bild unter eine freie Lizens zu stellen? (j/n)")
if zugestimmt == "j":
# hochladen
else:
# nicht hochladen
else:
# nicht hochladen





if hochladen:
print("Bild hochladen")
else:
print("Bild darf nicht hochgeladen werden")[/code]

ich weis nicht wie man dann immer auf die untere else abfrage springen kann. es kann sein dass es ein verständnissproblem von mir mit der aufgabe ist. der proff meinte nur bei nachfrage: "nur eine einzge print abfrage undzwar die die dort unten setht!" wir haben auch nciht viele weitere befehle und funktionen behandelt, sprich dürfen jetzt nicht viel mir noch unbekanntes einbauen.

ich möchte eigendlich auch garnicht den richtigen code wissen, sondern nur hilfe zum seber machen.
bei hilfe wäre ich euch sehr verbunden.
danke schonmal

mfg
Zuletzt geändert von Anonymous am Freitag 28. Oktober 2016, 14:57, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Codebox-Tags gesetzt.
Sirius3
User
Beiträge: 17754
Registriert: Sonntag 21. Oktober 2012, 17:20

@Kandalius: Springen tust Du ja schon mit Deinen if-else-Blöcken. Und ganz automatisch landest Du irgendwann auch beim letzten if. Dort wird eine boolsche Variable hochladen verwendet. Und da ihr noch nirgends eine Wert zugewiesen worden ist, ist das vermutlich Deine Aufgabe, dies zu tun.
Kandalius
User
Beiträge: 3
Registriert: Freitag 28. Oktober 2016, 14:20

ok ich versuche mal zu verstehen wie du das meinst.

zwei variablen noch oben reinpacken
zB:
hochladen = true
verwerfen = false

und dann bei einer stelle die dann bei der antwort mit ja das bild hochladen lassen soll true angeben?

sorry wenn das grad blödsinn ist, aber ich bin einfach noch ziemlich weit am anfang mit python hab grad noch ne blockade
BlackJack

@Kandalius: Es wird im Gerüst `hochladen` verwendet. Das muss zu dem Zeitpunkt wo es verwendet wird entweder `True` oder `False` sein. Also musst Du diesen Wert auch setzen. Jedes mal wenn im Code fest steht ob man das Bild hochladen darf oder nicht, muss dieser Namen entsprechend an `True` oder `False` gebunden werden.

Du hast da übrigens keinen Entscheidungsbaum, sondern einen Graphen. In einem Baum hat jeder Knoten nur einen Elternknoten, in dem Graphen dort gibt es aber zwei Knoten die über zwei verschiedene Wege erreicht werden können. Das kann kann man mit einem grossen ``if``/``else``-*Baum* im Code nicht abbilden. Jedenfalls nicht ohne in verschiedenen Zweigen exakt den gleichen Code zu wiederholen, was etwas ist was Programmierer nicht machen. Dafür gibt es Funktionen, dass man Code an verschiedenen Stellen gebraucht wird, nur *einmal* schreibt und dann jeweils an den Stellen aufrufen kann.

Du berücksichtigst ebenfalls nicht, dass es eine Frage in dem Graphen gibt, bei der es nicht nur zwei Antworten (j/n) sondern drei gibt: ja, nein, und unbekannt.
Benutzeravatar
pillmuncher
User
Beiträge: 1484
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

  • lizens ist kein deutsches Wort.
  • die Zeilen 29-52 sind falsch eingerückt.
In specifications, Murphy's Law supersedes Ohm's.
Sirius3
User
Beiträge: 17754
Registriert: Sonntag 21. Oktober 2012, 17:20

Auch wenn das eine Hausaufgabe ist, ist die Lösung glaube ich genauso, als ob BlackJack wieder irgendeine exotische Programmiersprache benutzt:

Code: Alles auswählen

from collections import namedtuple

Node = namedtuple('Node', 'question,yes,no')

third_party_graph = Node("Sind Bildrechte Dritter ausgeschlossen?",
    True,
    Node("Hast du das schriftliche Einverstaendnis aller Betroffenen?", True, False)
)

upload_graph = Node("Hast Du das Bild selbst erstellt?",
    Node("Willst du das Bild unter einer in der Wikipedia zulaessigen Lizens veroeffentlichen?",
        third_party_graph,
        False
    ),
    Node("Ist das Bild mehr als 100 Jahre alt?",
        True,
        Node("Ist der Urheber des Bildes bekannt?",
            Node("Ist der Urheber vor mehr als 70 Jahren verstorben?",
                third_party_graph,
                Node("Hat der Urheber des Bides zugestimmt, das Bild unter eine freie Lizens zu stellen?", True, False)
            ),
            False
        )
    )
)

def traverse_graph(graph):
    while True:
        answer = input("{} (j/n) ".format(graph.question))
        if answer in ('j', 'n'):
            break
    graph = graph.yes if answer == 'j' else graph.no
    return graph if graph in (True, False) else traverse_graph(graph)

print("Bild {}hochladen".format("" if traverse_graph(upload_graph) else "nicht "))
BlackJack

@Sirius3: Ich weiss jetzt gaaar nicht was Du meinst. :-D

Ist JavaScript exotisch?
[codebox=javascript file=Unbenannt.js]'use strict';

var readlineSync = require('readline-sync');

var makeAnswer = function (value) {
return function () { return value };
};

var JA = makeAnswer(true);
var NEIN = makeAnswer(false);

var makeQuestion = function (text, answerToQuestion) {
if (answerToQuestion === undefined) answerToQuestion = {};
if (answerToQuestion['j'] === undefined) answerToQuestion['j'] = JA;
if (answerToQuestion['n'] === undefined) answerToQuestion['n'] = NEIN;
return function() {
while (true) {
var hints = Object.getOwnPropertyNames(answerToQuestion).join('/');
var response = readlineSync.question(text + ' ' + hints + ' ');
var question = answerToQuestion[response[0]];
if (question !== undefined) return question();
}
};
};

var main = function() {
var thirdPartyRights = makeQuestion(
'Sind Bildrechte Dritter auszuschliessen?',
{
'n': makeQuestion(
'Hast Du das schriftliche Einverständnis aller Betroffenen?'
)
}
);
var olderThan100Years = makeQuestion('Ist das Bild älter als 100 Jahre?');
var graph = makeQuestion(
'Hast Du das Bild selbst erstellt?',
{
'j': makeQuestion(
'Willst Du das Bild unter einer in der Wikipedia zulässigen freien' +
' Lizenz veröffentlichen?',
{'j': thirdPartyRights}
),
'n': makeQuestion(
'Ist der Urheber des Bildes bekannt?',
{
'j': makeQuestion(
'Ist der Urheber vor mehr als 70 Jahren verstorben?',
{
'j': thirdPartyRights,
'n': makeQuestion(
'Hat der Urheber des Bildes zugestimmt das Bild unter' +
' eine freie Lizenz zu stellen?'
),
'?': olderThan100Years
}
),
'n': olderThan100Years
}
)
}
)


if (graph()) {
console.log('Bild hochladen.');
} else {
console.log('Bild darf nicht hochgeladen werden.');
}
};

if (require.main === module) {
main();
}[/code]
Benutzeravatar
pillmuncher
User
Beiträge: 1484
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

Happy Continuations Day, Y'all!

Code: Alles auswählen

#!/usr/bin/env python
# coding: utf-8

def do_upload():
    return 'hochladen!'

def dont_upload():
    return 'nicht hochladen!'

def ask(question, yes=do_upload, no=dont_upload, unknown=None):
    def do_ask():
        v = input(question + ' (j/n{})'.format('' if unknown is None else '/u'))
        if v in 'jJ':
            return yes()
        elif v in 'nN':
            return no()
        elif v in 'uU':
            return unknown()
        else:
            raise ValueError('Falsche Eingabe!')
    return do_ask

ask_if_written_consent_of_all_concerned_exists = ask(
    'Hast du das schriftliche Einverstaendnis aller Betroffenen?')

ask_if_picture_is_more_than_100_years_old = ask(
    'Ist das Bild mehr als 100 Jahre alt?')

ask_if_originator_consents_to_free_license = ask(
    'Hat der Urheber des Bides zugestimmt, das Bild unter eine freie Lizenz '
    'zu stellen?')

ask_if_third_party_rights_exist = ask(
    'Sind Bildrechte Dritter ausgeschlossen?',
    no=ask_if_written_consent_of_all_concerned_exists)

ask_if_picture_should_be_published_under_free_license = ask(
    'Willst du das Bild unter einer in der Wikipedia zulaessigen Lizenz '
    'veroeffentlichen?',
    yes=ask_if_third_party_rights_exist)

ask_if_originator_died_more_than_70_years_ago = ask(
    'Ist der Urheber vor mehr als 70 Jahren verstorben?',
    yes=ask_if_third_party_rights_exist,
    no=ask_if_originator_consents_to_free_license,
    unknown=ask_if_picture_is_more_than_100_years_old)

ask_if_originator_is_established = ask(
    'Ist der Urheber des Bildes bekannt?',
    yes=ask_if_originator_died_more_than_70_years_ago,
    no=ask_if_picture_is_more_than_100_years_old)

ask_if_picture_is_selfmade = ask(
    'Hast du das Bild selbst erstellt?',
    yes=ask_if_picture_should_be_published_under_free_license,
    no=ask_if_originator_is_established)

decide = ask_if_picture_is_selfmade

def main():
    print(decide())

if __name__ == '__main__':
    main()
In specifications, Murphy's Law supersedes Ohm's.
Benutzeravatar
pillmuncher
User
Beiträge: 1484
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

Code: Alles auswählen

%s/ask_if_third_party_rights_exist/ask_if_no_third_party_has_copyright_claim
Yay! 1 Kilo-Posting :D
In specifications, Murphy's Law supersedes Ohm's.
BlackJack

@pillmuncher: Gratulation. 8)

@all: Ich wollte ja schon immer mal was mit `singledispatch` machen:

Code: Alles auswählen

#!/usr/bin/env python
# coding: utf8
from __future__ import absolute_import, division, print_function
from collections import namedtuple
from singledispatch import singledispatch


class Question(object):

    def __init__(self, question, yes=True, no=False, unknown=None):
        self.question = question
        self.yes = yes
        self.no = no
        self.unknown = unknown


@singledispatch
def traverse(obj):
    raise TypeError(
        'can not traverse value {0!r} of type {1}'.format(obj, type(object))
    )


@traverse.register(bool)
def traverse_bool(value):
    return value


@traverse.register(Question)
def traverse_question(question):
    while True:
        hints = 'j/n' + ('' if question.unknown is None else '/u')
        response = raw_input('{0} {1}: '.format(question.question, hints)).lower()
        if response == 'j':
            return traverse(question.yes)
        elif response == 'n':
            return traverse(question.no)
        elif question.unknown is not None and response == 'u':
            return traverse(question.unknown)


def main():
    third_party_rights = Question(
        'Sind Bildrechte Dritter auszuschliessen?',
        no=Question('Hast Du das schriftliche Einverständnis aller Betroffenen?')
    )
    older_than_100_years = Question('Ist das Bild älter als 100 Jahre?')
    graph = Question(
        'Hast Du das Bild selbst erstellt?',
        yes=Question(
            'Willst Du das Bild unter einer in der Wikipedia zulässigen freien'
            ' Lizenz veröffentlichen?',
            yes=third_party_rights
        ),
        no=Question(
            'Ist der Urheber des Bildes bekannt?',
            yes=Question(
                'Ist der Urheber vor mehr als 70 Jahren verstorben?',
                yes=third_party_rights,
                no=Question(
                    'Hat der Urheber des Bildes zugestimmt das Bild unter'
                    ' eine freie Lizenz zu stellen?'
                ),
                unknown=older_than_100_years
            ),
            no=older_than_100_years
        )
    )
    print(traverse(graph))


if __name__ == '__main__':
    main()
BlackJack

Nachdem `singledispatch` ja eine nette Vorstufe zu Klassen/Methoden ist, hier eine Umsetzung in Java, wo's ohne Klassen ja nicht wirklich geht.
[codebox=java5 file=Unbenannt.java]public interface Evaluable {

boolean evaluate();
}[/code]
[codebox=java5 file=Unbenannt.java]public class Answer implements Evaluable {
public static final Evaluable YES = new Answer(true);
public static final Evaluable NO = new Answer(false);
private final boolean value;

private Answer(boolean value) {
this.value = value;
}

@Override
public boolean evaluate() {
return this.value;
}
}[/code]
[codebox=java5 file=Unbenannt.java]import java.util.Scanner;

public class Question implements Evaluable {

private final String question;
private Evaluable yes = Answer.YES;
private Evaluable no = Answer.NO;
private Evaluable unknown = null;

public Question(String question) {
this.question = question;
}

public Question setYes(Evaluable evaluable) {
this.yes = evaluable;
return this;
}

public Question setNo(Evaluable evaluable) {
this.no = evaluable;
return this;
}

public Question setUnknown(Evaluable evaluable) {
this.unknown = evaluable;
return this;
}

private String getQuestion() {
final String hints = " j/n" + ((this.unknown == null) ? "" : "/u");
return this.question + hints + ": ";
}

@Override
public boolean evaluate() {
final Scanner input = new Scanner(System.in, "utf8");
final String question = getQuestion();
while (true) {
System.out.print(question);
final String line = input.nextLine().toLowerCase();
if (!line.isEmpty()) {
switch (line.charAt(0)) {
case 'j':
return this.yes.evaluate();
case 'n':
return this.no.evaluate();
case 'u':
if (this.unknown != null) {
return this.unknown.evaluate();
}
}
}
}
}
}[/code]
[codebox=java5 file=Unbenannt.java]public class Main {

public static void main(String[] args) {
final Evaluable thirdPartyRights =
(new Question("Sind Bildrechte dritter auszuschliessen?"))
.setNo(new Question("Hast Du das schriftliche Einverständnis" +
" aller Betroffenen?"));

final Evaluable olderThan100Years =
new Question("Ist das Bild älter als 100 Jahre?");

final Evaluable questions =
(new Question("Hast Du das Bild selbst erstellt?"))
.setYes((new Question("Willst Du das Bild unter einer in der" +
" Wikipedia zulässigen freien Lizenz veröffentlichen?"))
.setYes(thirdPartyRights))
.setNo((new Question("Ist der Urheber des Bildes bekannt?"))
.setYes((new Question("Ist der Urheber des Bildes vor" +
"über 70 Jahren verstorben?"))
.setYes(thirdPartyRights)
.setNo(new Question("Hat der Urheber des" +
" Bildes zugestimmt das Bild unter" +
" eine freie Lizenz zu stellen?"))
.setUnknown(olderThan100Years))
.setNo(olderThan100Years));

final boolean upload = questions.evaluate();
System.out.println("Bild " + (upload ? "" : "nicht ") + "hochladen");
}
}[/code]
Sirius3
User
Beiträge: 17754
Registriert: Sonntag 21. Oktober 2012, 17:20

Irgendwie waren mir die Antwortmöglichkeiten noch zu eingeschränkt:

Code: Alles auswählen

third_party_rights = {
    '?': "Sind Bildrechte dritter auszuschliessen?",
    'sicher': True,
    'ähm': {
        '?': "Hast Du das schriftliche Einverständnis aller Betroffenen?",
        'jup': True,
        'ups': False,
    }
}

older_than_100years = {
    '?': "Ist das Bild älter als 100 Jahre?",
    'uralt': True,
    'neuer': False,
}

upload_questions = {
    '?': "Hast Du das Bild selbst erstellt?",
    'freilich': {
        '?': "Willst Du das Bild unter einer in der Wikipedia zulässigen freien Lizenz veröffentlichen?",
        'klar': third_party_rights,
        'niemals': False
    },
    'nee': {
        '?': "Ist der Urheber des Bildes bekannt?",
        'bekannt': {
            '?': "Ist der Urheber des Bildes vor über 70 Jahren verstorben?",
            'ja': third_party_rights,
            'nein': {
                '?': "Hat der Urheber des Bildes zugestimmt das Bild unter eine freie Lizenz zu stellen?",
                'schon': True,
                'naja': False,
            },
            'vielleicht': older_than_100years,
        },
        'unbekannt': older_than_100years,
    }
}

def answer_question(question):
    question = dict(question)
    prompt = question.pop('?')
    hints = '/'.join(sorted(question))
    while True:
        response = input("{} ({}) ".format(prompt, hints))
        try:
            answer = question[response]
            break
        except KeyError:
            pass
    if answer in (True, False):
        return answer
    else:
        return answer_question(answer)

print("Bild {}hochladen".format("" if answer_question(upload_questions) else "nicht "))
BlackJack

Da es ja irgendwie schön wäre wenn man die Fragen/Antworten komplett als Daten ausdrücken könnte, bietet sich YAML als Format an, weil man dort Anker (&…) auf Dokumentteile setzen kann, auf die man sich an anderer Stelle dann über eine Referenz (*…) beziehen kann:
[codebox=yaml file=Unbenannt.yml]'?': Hast Du das Bild selbst erstellt?
freilich:
'?': >-
Willst Du das Bild unter einer in der Wikipedia zulässigen freien Lizenz
veröffentlichen?
klar: &third_party_rights
'?': Sind Bildrechte dritter auszuschliessen?
sicher: true
ähm:
'?': Hast Du das schriftliche Einverständnis aller Betroffenen?
jup: true
ups: false
niemals: false
nee:
'?': Ist der Urheber des Bildes bekannt?
bekannt:
'?': Ist der Urheber des Bildes vor über 70 Jahren verstorben?
ja: *third_party_rights
nein:
'?': >-
Hat der Urheber des Bildes zugestimmt das Bild unter eine freie Lizenz
zu stellen?
schon: true
naja: false
vielleicht: &older_than_100_years
'?': Ist das Bild älter als 100 Jahre?
uralt: true
neuer: false
unbekannt: *older_than_100_years[/code]
Ein YAML-Modul und drei, vier Zeilen Code um die Datei zu laden und Sirius3's Programm kann für beliebige Fragenkataloge verwendet werden. :-)
Benutzeravatar
pillmuncher
User
Beiträge: 1484
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

Die Input-Operation sollte man herauslösen, damit man es auch ohne Benutzereingabe testen kann. Und mit Monaden wird alles besser:

Code: Alles auswählen

#!/usr/bin/env python
# coding: utf-8

from __future__ import print_function


class Either:

    def __init__(self, value):
        self.value = value

    @staticmethod
    def unit(value):
        return Right(value)

    def fmap(self, f):
        return type(self)(f(self.value))


class Right(Either):

    def bind(self, mf):
        return mf(self.value)


class Left(Either):

    def bind(self, mf):
        return self


def traverse(f):
    def t(m):
        return f(m).bind(t)
    return t


def ask(**kwargs):
    return Right(kwargs)


def tell(answer):
    return Left(answer)


sure = tell('hochladen!')
nope = tell('nicht hochladen!')
fail = tell('Falsche Eingabe!')


def dispatch(f, d):
    def disp(question, yes=sure, no=nope, unknown=fail):
        v = f(**d)
        if v in 'jJ':
            return yes
        elif v in 'nN':
            return no
        elif v in 'uU':
            return unknown
        else:
            return fail
    return disp(**d)


ask_if_written_consent_of_all_concerned_exists = ask(
    question='Hast du das schriftliche Einverstaendnis aller Betroffenen?')

ask_if_picture_is_more_than_100_years_old = ask(
    question='Ist das Bild mehr als 100 Jahre alt?')

ask_if_originator_consents_to_free_license = ask(
    question=('Hat der Urheber des Bides zugestimmt, das Bild unter eine '
              'freie Lizenz zu stellen?'))

ask_if_third_party_rights_exist = ask(
    question='Sind Bildrechte Dritter ausgeschlossen?',
    no=ask_if_written_consent_of_all_concerned_exists)

ask_if_picture_should_be_published_under_free_license = ask(
    question=('Willst du das Bild unter einer in der Wikipedia zulaessigen '
              'Lizenz veroeffentlichen?'),
    yes=ask_if_third_party_rights_exist)

ask_if_originator_died_more_than_70_years_ago = ask(
    question='Ist der Urheber vor mehr als 70 Jahren verstorben?',
    yes=ask_if_third_party_rights_exist,
    no=ask_if_originator_consents_to_free_license,
    unknown=ask_if_picture_is_more_than_100_years_old)

ask_if_originator_is_established = ask(
    question='Ist der Urheber des Bildes bekannt?',
    yes=ask_if_originator_died_more_than_70_years_ago,
    no=ask_if_picture_is_more_than_100_years_old)

ask_if_picture_is_selfmade = ask(
    question='Hast du das Bild selbst erstellt?',
    yes=ask_if_picture_should_be_published_under_free_license,
    no=ask_if_originator_is_established)


@traverse
def query(d):
    def q(question, unknown=None, **kwargs):
        u = '' if unknown is None else '/u'
        return input('{} (J/n{}) '.format(question, u)).strip()
    return dispatch(q, d)


def test_input(question, keys, result):
    @traverse
    def run(d):
        return dispatch(lambda **_: next(iter_keys), d)
    iter_keys = iter(keys)
    assert question.bind(run).fmap(result.value.__eq__).value


def main():
    question = ask_if_picture_is_selfmade
    question.bind(query).fmap(print)
    test_input(question, 'njuj', sure)
    test_input(question, 'njun', nope)
    test_input(question, 'nju_', fail)


if __name__ == '__main__':
    main()
In specifications, Murphy's Law supersedes Ohm's.
BlackJack

@pillmuncher: Das mit der Benutzerinteraktion hatte ich mir bei dem Java-Code auch schon gedacht, hab's dann aber wegen YAGNI sein gelassen, denn dann hätte ich zwei UIs implementieren müssen, damit sich das lohnt. Zum Testen gibt's `mock`. ;-)

@all: Zu dem YAML aus meinem letzten Beitrag jetzt noch ein Programm. In Rust (für das es leider keine Syntaxhervorhebung hier im Forum gibt :-():
[codebox=text file=Unbenannt.txt]extern crate yaml_rust;
use std::io::{self, Write};
use yaml_rust::{Yaml, YamlLoader};


const QUESTIONS: &'static str = include_str!("questions.yaml");


fn input(prompt: &str) -> io::Result<String> {
print!("{}", prompt);
try!(io::stdout().flush());
let mut answer = String::new();
try!(io::stdin().read_line(&mut answer));
Ok(answer.trim().to_string())
}


fn ask_question(yaml: &Yaml) -> io::Result<bool> {
let hints =
yaml.as_hash().unwrap()
.keys()
.filter_map(|x| {
let s = x.as_str().unwrap();
if s == "?" { None } else { Some(s) }
})
.collect::<Vec<&str>>()
.join("/");
let question = yaml["?"].as_str().unwrap();
let prompt = format!("{} ({}) ", question, hints);
loop {
let answer = try!(input(&prompt));
let next_yaml = &yaml[&*answer];
if !next_yaml.is_badvalue() {
return traverse_yaml(next_yaml);
}
}
}


fn traverse_yaml(yaml: &Yaml) -> io::Result<bool> {
match *yaml {
Yaml::Hash(_) => ask_question(yaml),
Yaml::Boolean(result) => Ok(result),
_ => panic!("unexpected Yaml type {:?}", yaml),
}
}


fn main() {
let docs = YamlLoader::load_from_str(QUESTIONS).unwrap();
match traverse_yaml(&docs[0]) {
Ok(may_upload) =>
println!("Bild {}hochladen.", if may_upload {""} else {"nicht "}),
Err(error) => println!("{:?}", error),
}
}[/code]
Die YAML-Datei wird direkt beim kompilieren in das Programm eingebettet. Darum behandle ich auch nur Fehler die bei der Eingabe während der Laufzeit auftreten können. Das müsste man natürlich ausbauen wenn die Fragen/Antworten auch zur Laufzeit geladen werden können sollen.
BlackJack

Nach den ganzen strukturierten „high level“-Lösungen noch eine die aus einer Zeit stammen könnte als es Wikipedia noch nicht gab: Ein BASIC-Programm für den C64:
[codebox=locobasic file=Unbenannt.txt] 10 u=0:cr$=chr$(13):print chr$(14):poke 53280,0:poke 53281,0
20 print"{blue}{clear}Wikipedia{red} - hochladen von Bildern"
100 q$="Hast Du das Bild selbst erstellt":gosub 2000:on a goto 500
200 q$="Willst Du das Bild unter einer in"+cr$
210 q$=q$+"der Wikipedia zulaessigen freien"+cr$
220 q$=q$+"Lizenz veroeffentlichen":gosub 2000:on a goto 1010
300 q$="Sind Bildrechte Dritter"+cr$+"auszuschliessen":gosub 2000:on a goto 400
310 goto 1000
400 q$="Hast Du das schriftliche"+cr$+"Einverstaendnis aller Betroffenen"
410 gosub 2000:on a+1 goto 1000,1010
500 q$="Ist der Urheber des Bildes bekannt":gosub 2000:on a goto 800
600 u=1:q$="Ist der Urheber vor mehr als"+cr$+"70 Jahren verstorben"
610 gosub 2000:u=0:on a+1 goto 300,700,800
700 q$="Hat der Urheber des Bildes"+cr$
710 q$=q$+"zugestimmt das Bild unter eine freie"+cr$
720 q$=q$+"Lizenz zu stellen":goto 410
800 q$="Ist das Bild aelter als 100 Jahre":goto 410
1000 n$="":goto 1020
1010 n$="nicht "
1020 print"{down}{purple}Bild ";n$;"hochladen.{red}":end
2000 print"{down}";q$;"? {purple}j/n";:if u then print"/u(nbekannt)";
2010 print"{red}"
2020 get a$:if a$="" then 2020
2030 if a$="j" then a=0:return
2040 if a$="n" then a=1:return
2050 if u and a$="u" then a=2:return
2060 goto 2000[/code]
Dazu hätte es dann noch einen Zettel gegeben auf dem handschriftlich der Entscheidungsgraph gezeichnet wäre, mit den Fragen von 1 bis 8 nummeriert, und dem Hinweis das jede der Fragen bei einer Hunderter-Zeilennummer beginnt (100: Frage 1, 200: Frage 2, …), bei 1000 der Einsprung zum Hochladen und 1010 der Einsprung zum nicht-hochladen ist, und bei 2000 das Unterprogramm, das dem Benutzer die aktuelle Frage (Q$) stellt und nach der Antwort (a) fragt. Und eine Liste mit den Variablennamen und einer Erklärung was sie bedeuten. :-)
Benutzeravatar
pillmuncher
User
Beiträge: 1484
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

In SWI-Prolog:[codebox=prolog file=Unbenannt.txt]question_0(
'Hast du das Bild selbst erstellt?',
question_1, question_2, answer_2).
question_1(
'Willst du das Bild unter einer in der Wikipedia zulaessigen Lizenz veroeffentlichen?',
question_5, answer_1, answer_2).
question_2(
'Ist der Urheber des Bildes bekannt?',
question_3, question_4, answer_2).
question_3(
'Ist der Urheber vor mehr als 70 Jahren verstorben?',
question_5, question_6, question_4).
question_4(
'Ist das Bild mehr als 100 Jahre alt?',
answer_0, answer_1, answer_2).
question_5(
'Sind Bildrechte Dritter ausgeschlossen?',
answer_0, question_7, answer_2).
question_6(
'Hat der Urheber des Bides zugestimmt, das Bild unter eine freie Lizenz zu stellen?',
answer_0, answer_1, answer_2).
question_7(
'Hast du das schriftliche Einverstaendnis aller Betroffenen?',
answer_0, answer_1, answer_2).

get_valid_chars(answer_2, ' (j/n)') :- !.
get_valid_chars(_, ' (j/n/u)').

ask(Question, Unknown, Atom) :-
write(Question),
get_valid_chars(Unknown, Valid),
writeln(Valid),
get_single_char(Char),
char_code(Atom, Char).

dispatch(j, Yes, _, _, Yes) :- !.
dispatch(n, _, No, _, No) :- !.
dispatch(_, _, _, Unknown, Unknown).

evaluate(answer_0, 'Hochladen!') :- !.
evaluate(answer_1, 'Nicht hochladen!') :- !.
evaluate(answer_2, 'Falsche Eingabe!') :- !.
evaluate(Q, Answer) :-
call(Q, Question, Yes, No, Unknown),
ask(Question, Unknown, Input),
dispatch(Input, Yes, No, Unknown, Next),
!, evaluate(Next, Answer).

run :-
evaluate(question_0, Answer),
writeln(Answer).[/code]
In specifications, Murphy's Law supersedes Ohm's.
BlackJack

Nochmal JavaScript, weil ich Daten und Programm mal trennen wollte in dem die Daten als Text und `id`- und `data-*`-Attribute im HTML stehen. Es gibt eine Liste von Fragen und eine Liste von Antworten als Listen im HTML. Die Graph-Struktur ist über `id` und `date-*`-Attribute abgebildet.

Keine Syntaxhervorhebung weil die nicht mit drei Sprachen (HTML, CSS, JavaScript) in einer Datei klar kommt. :-(
[codebox=text file=Unbenannt.txt]<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<title>Wikipedia — hochladen von Bildern</title>
<style type="text/css">
#ui {
width: 75%;
border: thin solid black;
padding: 2em;
}

.normal {
background-color: lightblue;
}

.positive {
background-color: lightgreen;
}

.negative {
background-color: lightpink;
}

ol#questions, ol#answers {
margin: 0;
padding: 0;
list-style: none;
}

.buttons {
border: medium ridge blue;
border-radius: 10px;
background-color: lightblue;
float: right;
padding: 1em;
}
</style>
</head>
<body>
<div id="ui">
<ol id="questions" data-start="#q1">
<li id="q1" data-yes="#q2" data-no="#q5">
Hast Du das Bild selbst erstellt?
</li>
<li id="q2" data-yes="#q3" data-no="#false">
Willst Du das Bild unter einer in der Wikipedia zulässigen freien Lizenz
veröffentlichen?
</li>
<li id="q3" data-yes="#true" data-no="#q4">
Sind Bildrechte Dritter auszuschliessen?
</li>
<li id="q4" data-yes="#true" data-no="#false">
Hast Du das schriftliche Einverständnis aller Betroffenen?
</li>
<li id="q5" data-yes="#q6" data-no="#q8">
Ist der Urheber des Bildes bekannt?
</li>
<li id="q6" data-yes="#q3" data-no="#q7" data-unknown="#q8">
Ist der Urheber vor mehr als 70 Jahren verstorben?
</li>
<li id="q7" data-yes="#true" data-no="#false">
Hat der Urheber des Bildes zugestimmt das Bild unter eine freie Lizenz
zu stellen?
</li>
<li id="q8" data-yes="#true" data-no="#false">
Ist das Bild älter als 100 Jahre?
</li>
</ol>

<ol id="answers">
<li id="true" data-reset="#q1">Bild hochladen.</li>
<li id="false" data-reset="#q1">Bild <em>nicht</em> hochladen.</li>
</ol>

<div class="buttons">
<button id="yes-button" data-answer-type="yes">Ja</button>
<button id="no-button" data-answer-type="no">Nein</button>
<button id="unknown-button" data-answer-type="unknown">Unbekannt</button>
<button id="reset-button" data-answer-type="reset">Neustart</button>
</div>
</div>
<script type="text/javascript">
var ANSWERS = ['yes', 'no', 'unknown', 'reset'];

var hide = function (element) {
element.style.display = 'none';
};

var show = function (element) {
element.style.display = '';
};

var hideAll = function (elements) {
for (var i = 0; i < elements.length; i++) hide(elements);
};

var Node = function (element) {
this.element = element;
};

Node.prototype.show = function () { show(this.element); };
Node.prototype.hide = function () { hide(this.element); };

Node.prototype.getPossibleAnswers = function () {
var result = {};
for (var i = 0; i < ANSWERS.length; i++) {
answer = ANSWERS;
id = this.element.dataset[answer];
if (id !== undefined) {
result[answer] = id;
}
}
return result;
};

Node.prototype.get = function (answer) {
return this.element.dataset[answer];
};

var Graph = function (elements, startId) {
var self = this;
this.nodes = {};
for (var i = 0; i < elements.length; i++) {
var element = elements;
var node = new Node(element);
node.hide();
this.nodes['#' + element.id] = node;
};
this.ui = document.querySelector('#ui');
this.buttonsElement = this.ui.querySelector('.buttons');
for (var i = 0; i < ANSWERS.length; i++) {
var answer = ANSWERS;
var button = this.buttonsElement.querySelector(
'#' + answer + '-button'
);
button.addEventListener('click', this.onChoice.bind(this, answer));
}

this.current = null;
this.moveTo(startId);
};

Graph.prototype.moveTo = function (nodeId) {
if (this.current !== null) {
this.current.hide();
}
this.current = this.nodes[nodeId];
this.current.show();
if (nodeId === '#true') {
this.ui.style.backgroundColor = 'lightgreen';
} else if (nodeId === '#false') {
this.ui.style.backgroundColor = 'lightpink';
} else {
this.ui.style.backgroundColor = 'lightblue'
}
this.updateButtons();
};

Graph.prototype.updateButtons = function () {
hideAll(this.buttonsElement.querySelectorAll('button'));
var possibleAnswers = this.current.getPossibleAnswers();
var answers = Object.keys(possibleAnswers);
for (var i = 0; i < answers.length; i++) {
var buttonId = '#' + answers + '-button';
show(this.buttonsElement.querySelector(buttonId));
}
};

Graph.prototype.onChoice = function (answer) {
this.moveTo(this.current.get(answer));
};

var elements = document.querySelectorAll('#ui li');
var startId = document.querySelector('#questions').dataset.start;
var graph = new Graph(elements, startId);
</script>
</body>
</html>[/code]
Antworten