Buch Cover Buch Cover Buch Cover Buch Cover

Web-Code: - Webcode Help

Code Knacken (Simulationen)

Hannas fünfstelliges Zahlenschloss wurde verstellt. Das Zahlenschloss besteht aus fünf Ringen mit je zehn möglichen Einstellungen ('0', '1', '2', ..., '9').


Irgend eine Klassenkameradin hat ihr den Code abgeschaut und nun neu eingestellt.
Die Klassenkameradin hat den neuen Code leider vergessen. Aufgrund von Lieblingszahlen und Mustern haben die beiden zusammen jedoch folgendes rekonstruieren können:

  • Der neue Code enthält keine 5.
  • Der neue Code enthält mindestens einmal die Ziffer 3.
  • Der neue Code enthält mindestens einmal die Ziffer 6.
  • Der neue Code startet nicht mit einer geraden Ziffer, auch nicht mit der Null ("0").
  • Der neue Code ist fast aufsteigend. Das heißt, die nachfolgenden Ziffern sind nicht kleiner als die vorangehenden (z. b. "23368"). Dies jedoch mit maximal einer Ausnahme. An einer Stelle darf die Ziffernfolge absteigend sein (z. b. 23326); aber wie erwähnt: maximal einmal!



Lohnt es sich nun, von den theoretisch 100'000 Möglichkeiten die verbleibenden auszuprobieren? Oder soll Hanna doch besser ein neues Zahlenschloss anschaffen.

Teilaufgabe 1: Schreiben Sie ein Programm, das alle verbleibenden
Möglichkeiten ausgibt.

Teilaufgabe 2: Hanna kann eine Kombination in drei (3) Sekunden ausprobieren. Gehen wir davon aus, dass sie die richtige Kombination nach Durchprobieren etwa der Hälfte aller Möglichkeiten gefunden haben wird; wird sie es in weniger als einer Stunde schaffen?

0 Kommentare

Bitte melde dich an um einen Kommentar abzugeben

7 Lösung(en)

package ch.programmieraufgaben.simulation.zahlenschloss;


/**
 * Programmieraufgabe Zahlenschloss
 * Web-Code: d4ko-cgvt
 * @version 0.1 (Apr 21, 2018)
 * @author Philipp Gressly Freimann 
 *         (phi@gress.ly)
 */
public class Zahlenschloss {

	final int ANZAHL_ZIFFERN       =      5;
	final int MAX_CODE             = 99_999;
	final int SEKUNDEN_PRO_VERSUCH =      3;

	public static void main(String[] args) {
		new Zahlenschloss().top();
	}


	void top() {
		int anzahlMoeglichkeiten = 0;
		for(int m = 0; m < MAX_CODE; m++) {
			if(istMoeglicherCode(m)) {
				anzahlMoeglichkeiten = anzahlMoeglichkeiten + 1;
				printMoeglichkeit(m);
			}
		}
		System.out.println("Total Möglichkeiten: " + anzahlMoeglichkeiten);
		int sekunden = anzahlMoeglichkeiten * SEKUNDEN_PRO_VERSUCH;
		int minuten  = sekunden / 60;
		System.out.println("Total Minuten für alle Möglichkeiten: " + minuten);
		System.out.println("Erwartungswert: " + minuten/2 + " Minuten.");
	}


	public boolean istMoeglicherCode(int m) {
		return okAufsteigend(m) &&
		       okZiffern(m)     &&
		       okNichtBeginnendMitGeraderZiffer(m);
	}


	boolean okNichtBeginnendMitGeraderZiffer(int m) {
		return   1 == ((codeToString(m)).charAt(0) - '0') % 2;
	}


	void printMoeglichkeit(int m) {
		System.out.println(m);
	}


	boolean okAufsteigend(int code) {
		return 1 >= anzahlAbstiege(code);
	}


	int anzahlAbstiege(int code) {
		int abstiege = 0;
		String codeZiffern = codeToString(code);
		for(int pos = 0; pos+1 < codeZiffern.length(); pos++) {
			if(codeZiffern.charAt(pos) > codeZiffern.charAt(pos+1)) {
				abstiege = abstiege + 1;
			}
		}
		return abstiege;
	}


	boolean okZiffern(int code) {
		return
		  !enthaeltZiffer('5', code) && 
		   enthaeltZiffer('3', code) &&
		   enthaeltZiffer('6', code);
	}


	String codeToString(int code) {
		String str = "" + code;
		while(str.length() < ANZAHL_ZIFFERN) {
			str = "0" + str;
		}
		return str;
	}


	boolean enthaeltZiffer(char ziffer, int code) {
		return (codeToString(code)).contains(""+ziffer);
	}

} // end of class Zahlenschloss

                

Lösung von: Philipp Gressly Freimann (SANTIS Training AG)

import time


def no_five(nr):
    if '5' in nr:
        return 1
    return 0


def used_three(nr):
    if '3' in nr:
        return 0
    return 2


def used_six(nr):
    if '6' in nr:
        return 0
    return 3


def starts_with_valid(nr):
    digit = int(nr[0])

    if digit == 0 or digit % 2 == 0:
        return 4
    return 0


def is_ascending(nr):
    exception = 1

    for i in range(0, len(nr) - 1):
        if int(nr[i]) > int(nr[i + 1]):
            exception -= 1

    if exception < 0:
        return 5
    return 0


def check_number(nr):
    ok = no_five(nr)
    if ok == 0:
        ok = used_three(nr)
    if ok == 0:
        ok = used_six(nr)
    if ok == 0:
        ok = starts_with_valid(nr)
    if ok == 0:
        ok = is_ascending(nr)

    return ok


number_of_codes = 0

print('start...')

t0 = time.time()

for i in range(0, 100000):
    code = '{0:05d}'.format(i)
    is_code = check_number(code)

    if is_code == 0:
        print('found code number {0}: {1}'.format(number_of_codes, code))
        number_of_codes += 1

print('finished!\n')

t1 = time.time()

print('found {0} valid codes in {1} seconds'.format(number_of_codes, t1 - t0))

seconds_per_code = 3

used_seconds = 0.5 * seconds_per_code * number_of_codes

print('the lock will be cracked in {0} seconds - that are {1} minutes and {2} seconds'.format(used_seconds,
                                                                                         used_seconds // 60,
                                                                                         used_seconds % 60))

                

Lösung von: Ich Bins (tubs)

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

"""
Code knacken
https://www.programmieraufgaben.ch/aufgabe/code-knacken/d4kocgvt
"""

# Programmieraufgabe:
#     Hannas fünfstelliges Zahlenschloss wurde verstellt. Das Zahlenschloss
#     besteht aus fünf Ringen mit je zehn möglichen Einstellungen ('0', '1', '2',
#     ..., '9').
#     Irgend eine Klassenkameradin hat ihr den Code abgeschaut und nun neu
#     eingestellt. Die Klassenkameradin hat den neuen Code leider vergessen.
#     Aufgrund von Lieblingszahlen und Mustern haben die beiden zusammen jedoch
#     folgendes rekonstruieren können:
#         Der neue Code enthält keine 5.
#         Der neue Code enthält mindestens einmal die Ziffer 3.
#         Der neue Code enthält mindestens einmal die Ziffer 6.
#         Der neue Code startet nicht mit einer geraden Ziffer, auch nicht mit
#         der Null ("0").
#         Der neue Code ist fast aufsteigend. Das heißt, die nachfolgenden Ziffern
#         sind nicht kleiner als die vorangehenden (z. b. "23368"). Dies jedoch
#         mit maximal einer Ausnahme. An einer Stelle darf die Ziffernfolge
#         absteigend sein (z. b. 23326); aber wie erwähnt: maximal einmal!
#     Schreiben Sie ein Programm, das alle verbleibenden Möglichkeiten ausgibt.
#
# Autor, Erstellung:
#     Ulrich Berntien, 2018-06-08
#
# Sprache:
#     Python 3.6.6


import itertools
from typing import *


def is_hannas_code(code: Tuple[int, ...]) -> bool:
    """
    Die Funktion prüft ob es eine Kombination von Hanna sein kann.
    :param code: Zu überprüfenden Zahlencode.
    :return: True, genau dann, wenn der Code von Hanna sein kann.
    """
    # Bereits vorher wurde festgelegt: keine 5 enthalten und erste Ziffer ungerade
    assert 5 not in code
    assert code[0] % 2 == 1
    # Ziffer 3 und 6 müssen enthalten sein
    # erste Ziffer muss ungerade und keine 0 sein
    # Nur maximal einmal darf die Ziffernfolge aufsteigend sein
    return 3 in code and \
           6 in code and \
           sum(a > b for (a, b) in zip(code, code[1:])) <= 1


print("Programmieraufgabe Code Knacken, http://www.programmieraufgaben.ch")
# Die Kombination besteht aus den Ziffer 0..9 ohne die Ziffer 5
hannas_digits = [digit for digit in range(10) if digit != 5]
# Die erste Ziffer muss ungerade und keine 0 sein.
hannas_first_digit = [digit for digit in hannas_digits if digit % 2 == 1]
# Hannas Kombination hat 5 Stellen und weitere Kritrien müssen erfüllt sein.
hannas_options = [code for code in itertools.product(hannas_first_digit, *(hannas_digits,) * 4) if is_hannas_code(code)]
for number in hannas_options:
    print(number)
print("Anzahl der Kombinationen:", len(hannas_options))
print("Bei 3s pro Kombination und 50% ausprobieren: {:.0f}min".format(len(hannas_options) * 3 / 2 / 60))
                

Lösung von: Ulrich Berntien ()

'12.6.2018 - Powerbasic 10

#COMPILE EXE
#DIM ALL

FUNCTION PBMAIN () AS LONG

DIM i AS LONG
DIM x AS INTEGER
DIM Loesung AS STRING
DIM AnzMgl AS LONG
DIM anzAbst AS INTEGER
DIM ZeitInMin AS INTEGER

FOR i = 00000 TO 99999
    'Startet nicht mit gerader Zahl, auch nicht 0
    IF (i \ 10000) MOD 2 = 0 THEN ITERATE
    'Enthält nicht die Ziffer 5
    IF LEN(RETAIN$(FORMAT$(i),ANY "5")) THEN ITERATE
    'Enthält mindestens einmal die Ziffern 3 und 6
    IF TALLY(FORMAT$(i),ANY "3") < 1 THEN ITERATE
    IF TALLY(FORMAT$(i),ANY "6") < 1 THEN ITERATE

    'Check Aufsteigend
    anzAbst = 0
    FOR x = 1 TO LEN(FORMAT$(i)) -1
        IF VAL(MID$(FORMAT$(i),x,1)) > VAL(MID$(FORMAT$(i),x+1,1)) THEN anzAbst += 1
    NEXT x
    IF anzAbst > 1 THEN ITERATE

    Loesung += FORMAT$(i) & $CRLF
    AnzMgl += 1
NEXT i


'Teilaufgabe 1
MSGBOX STR$(AnzMgl) & $CRLF & loesung

'Teilaufgabe 2
ZeitInMin = FIX((anzMgl * 3 / 2) / 60)
MSGBOX "Erwartet werden ca. " &  FORMAT$(ZeitInMin) & " Minuten für die Hälfte der Codes"

END FUNCTION


                

Lösung von: Markus Sägesser (keine)

def Zahlprüfen(x,y):                    # Funktion zum Prüfen von Ziffern y innerhalb einer Zahl x
    strx = str(x)                       # Umwandeln der Zahlen in Strings
    stry = str(y)
    if stry in strx:                    # Prüfung der Strings mit entsprechender Ausgabe True or False
        return True
    else:
        return False

def ErsteZifferPrüfen(x, y):
    strx = str(x)                       # Umwandeln der Zahlen in Strings
    stry = str(y)
    if strx.startswith(stry):           # Prüfung der Strings
        return True
    else:
        return False

def ZahlZuArray(x):
    l = len(str(x))                     # Bestimme Anzahl der Ziffern 
    A = [0]                             # Definiere Liste
    for k in range (0,l):                           # itteriere über alle Ziffern der Zahl 
        aneu = (x - (x%10**(l-k-1)))/10**(l-k-1)    # Berechne Listeneinträge beginnend von vorn
        x = x - aneu*10**(l-k-1)                    # kürze bisherige Zahl um höchste 10er Potenz genaue Erläuterungen siehe unten 
        A.append(aneu)                              # Füge neues Listenelement hinzu
        #print (repr(x).rjust(2), repr(aneu))
    del A[0]                                        # entferne ersten Listeneintrag (aus Definition vom Beginn) 
    return A

def FastAufsteigend(x):
    A = ZahlZuArray(x)
    l = len(A)
    pr = 0                                        # Prüfzahl zum zählen der aufsteigenden Stellen
    for k in range (0,l-1):
        if A[k] > A[k+1]:
            pr = pr + 1
            #print (repr("nicht Aufsteigend").rjust(2), repr(pr))
    if pr <= 1:
        return True
    else:
        return False 

code = 0
j = 1
while code < 99999:
    if ErsteZifferPrüfen(code,0) == True:   # Prüfung von Bedingung 4 (am meisten einschränkende)
        code = code + 10**4
    elif ErsteZifferPrüfen(code,2) == True:
        code = code + 10**4
    elif ErsteZifferPrüfen(code,4) == True:
        code = code + 10**4
    elif ErsteZifferPrüfen(code,5) == True:
        code = code + 10**4
    elif ErsteZifferPrüfen(code,6) == True:
        code = code + 10**4
    elif ErsteZifferPrüfen(code,8) == True:
        code = code + 10**4
    elif FastAufsteigend(code) == False:    # Prüfung von Bedingung 5
        code = code + 1
    elif Zahlprüfen(code, 5) == True:       # Prüfung von Bedingung 1
        code = code + 1
    elif Zahlprüfen(code, 3) == False:      # Prüfung von Bedingung 2
        code = code + 1
    elif Zahlprüfen(code, 6) == False:      # Prüfung von Bedingung 3
        code = code + 1
    else:
        print (repr(j).rjust(2) , repr(code))
        code = code + 1
        j = j+1

"""
Berechnung der Listenelemente für eine gegebene natürliche Zahl

Sei x eine n-stellige natürliche Zahl, dann lässt sich x schreiben als

    x = sum_(i=0)^n d_i*10^i

Dabei sind d_i Elemente aus {0,1,2,...,9}. Ziel ist es nun diese d_i schrittweise zu isolieren. Mit obiger Darstellung gilt

   x mod 10^(n-1)       = sum_(i=0)^(n-1) d_i*10^i
=> x - x mod 10^(n-1)   = sum_(1=0)^n d_i*10^i - sum_(i=0)^(n-1) d_i*10^i
                        = d_n*10^n

Der Übersicht halber sei nun a = x - x mod 10^(n-1). Damit folgt offensichtlich

    a / 10^n = d_n*10^n/10^n = d_n
"""

                

Lösung von: Name nicht veröffentlicht

# Autor:	Remo Spichtig
# Task:		Code Knacken

#verständliche lösung:

from itertools import product as pr

def cor( val ):
	if 5 in val:
		return False
	if 3 not in val:
		return False
	if 6 not in val:
		return False
	if val[0] % 2 == 0:
		return False
	if sum([val[i] > val[i+1] for i in range(len(val)-1)]) > 1:
		return False
	return True
	
moegliche = []

for i in pr([0,1,2,3,4,5,6,7,8,9], repeat=5):
	if cor(i):
		moegliche.append(i)

print(len(moegliche))

for i in moegliche:
	print(i)
	
print("Wenn sie alle 3 sek. eine Kombination probiert wird sie höchstens {0} min benötigen.".format(3*len(moegliche)/60))
print("Wenn sie worst-case inerhalb einer Stunde fertig sein will müsste sie alle {0} sek. eine Kombination versuchen.".format(round(360/155,3)))


#schnellere lösung:


def dfs(code, absteigend, drei, sechs):
	if len(code) == 5:
		if drei and sechs:
			print(code)
	else:
		for i in [0,1,2,3,4,6,7,8,9]:
			if i >= code[-1] or not absteigend:
				dfs(code+[i], absteigend or i < code[-1], drei or i == 3, sechs or i == 6)
	
for i in [1,3,7,9]:
	dfs([i],False, i == 3, i == 6)
                

Lösung von: remo spichtig (BBW)

using System;
using System.Linq;

namespace Schloss_knacken
{
    class Program
    {
        static void Main(string[] args)
        {
            int Zutreffend = 0;
            TimeSpan Zeit = new TimeSpan(0, 0, 0);

            for(int i = 0; i < 100000; i++)
            {
                bool Fail = false;
                string Zahl = i.ToString();
                int Failstack = 0;

                if(i.ToString().Length < 5)
                {
                    for(int k = 0; k < 5 - i.ToString().Length; k++)
                    {
                        Zahl = "0" + Zahl;
                    }
                }

                // Abfragen ob bestimmte Zeichen enthalten sind
                if (Zahl.Contains('5') || !Zahl.Contains('3') || !Zahl.Contains('6')) Fail = true;

                //Abfrage ob der Start eine gerade Zahl ist
                if(Zahl.Substring(0,1) == "0" || Int32.Parse(Zahl.Substring(0,1)) % 2 == 0) Fail = true;

                //Abfrage nach größerer Ziffer
                for(int k = 0; k < Zahl.Length -1; k++)
                {
                    int Wert1 = Int32.Parse(Zahl.Substring(k, 1));
                    int Wert2 = Int32.Parse(Zahl.Substring(k + 1, 1));

                    if(Wert1 > Wert2) Failstack++;
                }

                if(Failstack > 1) Fail = true;


                if (Fail == false)
                {
                    Zutreffend++;
                    Zeit = Zeit.Add(new TimeSpan(0, 0, 3));
                }
            }

            Console.WriteLine("Zutreffende Werte = " + Zutreffend.ToString());
            Console.WriteLine("Höchstwert = " + Zeit.TotalMinutes + "min");
            Console.WriteLine("Erwartungswert = " + Zeit.TotalMinutes / 2 + "min");
            Console.ReadLine();
        }
    }
}
                

Lösung von: Tobias Golz (Adolf Kolping Berufskolleg)

Verifikation/Checksumme:

Total Möglichkeiten: 1550
Total Minuten für alle Möglichkeiten: 77
Erwartungswert: 38 Minuten.

Aktionen

Bewertung

Durchschnittliche Bewertung:

Eigene Bewertung:
Bitte zuerst anmelden

Meta

Zeit: 2
Schwierigkeit: Mittel
Webcode: d4ko-cgvt
Autor: Philipp Gressly Freimann (SANTIS Training AG)

Download PDF

Download ZIP

Zu Aufgabenblatt hinzufügen