Hackerboard Wiki HaboBlog
Hackerboard bei Facebook Hackerboard bei Google+ Hackerboard bei Twitter

[HaBo]

 
Programmieraufgaben Hier wird regelmäßig eine neue Programmieraufgabe gestellt, die dann gelöst werden soll und in Zusammenarbeit mit den Moderatoren auch besprochen werden kann.

Springerproblem

Diskussion: Springerproblem im Forum Programmieraufgaben, in der Kategorie Code Kitchen; Anzeige Hallo Leute, diese Aufgabe stammt von crux und es handelt sich um ein Schachproblem. Es geht darum einen Springer ...

Antwort
Alt 24.06.05, 22:06   #1 (permalink)
 
Registriert seit: 02.10.01
Nornagest Leistung: Facit NTK
Likes: 0
Standard Springerproblem

Anzeige

Hallo Leute,
diese Aufgabe stammt von crux und es handelt sich um ein Schachproblem.
Es geht darum einen Springer von einem beliebigen Feld aus alle Felder des Schachbretts besuchen zu lassen, ohne ein Feld zweimal zu betreten.

Die Aufgabe ist lösbar, ich wünsche euch viel Spaß. :)

Norna

Nornagest ist offline   Mit Zitat antworten
Alt 24.06.05, 23:11   #2 (permalink)
 
Registriert seit: 28.10.04
ich_bins Leistung: Z3
Likes: 3
Standard

nun hier ist des Rätsles Lösung...war eine in meinem Schachclub ne beliebte Aufgabe für neue Mitglieder ;-)

1. d4
2. c2
3. a1
4. b3
5. c1
6. a2
7. b4
8. d3
9. c5
10. a6
11. b8
12. d7
13. f6
14. e8
15. g7
16. h5
17. g3
18. h1
19. f2
20. e4
21. d6
22. b5
23. a7
24. c8
25. e7
26. g8
27. h6
28. f5
29. h4
30. g2
31. e1
32. f3
33. e5
34. f7
35. h8
36. g6
37. f8
38. h7
39. g5
40. e6
41. f4
42. h3
43. g1
44. e2
45. c3
46. d1
47. b2
48. a4
49. b6
50. a8
51. c7
52. d5
53. e3
54. g4
55. h2
56. f1
57. d2
58. b1
59. a3
60. c4
61. a5
62. b7
63. d8
64. c6

gruss...ich
ich_bins ist offline   Mit Zitat antworten
   
HaBOT
 
- Anzeige -

Werbung ist gerade online    
Alt 25.06.05, 12:39   #3 (permalink)
Themenstarter
 
Registriert seit: 02.10.01
Nornagest Leistung: Facit NTK
Likes: 0
Standard

Danke für die Lösung, allerdings geht es darum ein Programm zu schreiben dass das Problem löst. (und bitte nicht indem es die Liste vorgegeben hat und nur ausgibt)

Aber danke, ist sicher hilfreich zum vergleichen, ohne gleich alles nachzuspielen.
Nornagest ist offline   Mit Zitat antworten
Alt 25.06.05, 13:19   #4 (permalink)
 
Registriert seit: 03.12.04
Boar Leistung: Facit NTK
Likes: 0
Standard

Wow, hier tut sich ja mal wieder was.

Das klingt nach einem typischen Backtracking-Problem, bin mal gespannt wann die erste Lösung kommt. (ich setz mich heut oder morgen auch mal dran)

Gruß, Boar
Boar ist offline   Mit Zitat antworten
Alt 25.06.05, 15:12   #5 (permalink)
 
Registriert seit: 28.10.04
ich_bins Leistung: Z3
Likes: 3
Standard

Zitat:
[Habo] ? Software Home ? Code Kitchen ? Programmieraufgaben
sorry, hab ich net aufgepasst

gruss...ich
ich_bins ist offline   Mit Zitat antworten
Alt 28.06.05, 13:33   #6 (permalink)
 
Registriert seit: 03.12.04
Boar Leistung: Facit NTK
Likes: 0
Standard

So, hat zwar etwas länger gedauert (Abi-Stress), aber hier kommt meine Lösung.

Das Ganze war komplizierter als gedacht. Im Moment ist mein Algorithmus auch noch nicht für ein normales Schachbrett zu gebrauchen (dauert zu lange). Bei 5x5 oder 6x6 Feldern brauch der Algo auf meinem Rechner keine ganze Sekunde. Bei 7x7 sind es ca. 5 Sekunden und bei 8x8 Feldern hab ich nach einer Minute abgebrochen . Es hängt im Moment aber nur am Rechenaufwand, die Lösung funktioniert ansonsten. Ich werd aber noch dran arbeiten, den Lösungsweg zu beschleunigen.

Zu erklären gibt es eigentlich nicht viel, ich hab ein paar vereinzelte Kommentare im Code, der Rest dürfte selbsterklärend sein. Die GUI ist nicht schick, aber erfüllt ihren Zweck. Die Felgröße steht im Moment fest auf 6x6.

Achso, Programmiersprache = Java (1.4.2)
Ich hab das ganze als .jar-file in den Anhang gepackt.

Springerproblem.java:
Code:
package prog;

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.*;
import javax.swing.border.LineBorder;

public class Springerproblem extends JFrame implements ActionListener
{
    static int a = 6;
    Container cp = getContentPane();
    static JLabel[][] feld   = new JLabel[a][a];
    static int position[][] = new int[a][a];
    JPanel brett = new JPanel();
    JTextField coords = new JTextField("x,y",8);
    JLabel info = new JLabel("Starkoordinaten (von 0,0 bis "+(a-1)+","+(a-1)+"):");
    JButton start = new JButton("Berechnen");
    
    public Springerproblem()
    {
        super("Springerproblem");      
        this.setSize(350,400);
        this.setLocation((this.getToolkit().getScreenSize().width  - getSize().width ) / 2,
                         (this.getToolkit().getScreenSize().height - getSize().height) / 2);
        this.setResizable(false);
        this.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
        cp.setLayout(new FlowLayout(FlowLayout.LEFT,50,20));
        cp.add(brett);
        cp.add(info);
        cp.add(coords);
        cp.add(start);   
        brett.setLayout(new GridLayout(a,a));
        brett.setPreferredSize(new Dimension(200,200));
        info.setPreferredSize(new Dimension(350,13));
           
        for(int j=0; j<a; j++)
        {
          for(int i=0; i<a; i++)
          {
              feld[i][j]=new JLabel(" ",JLabel.CENTER);
              feld[i][j].setBorder( new LineBorder(Color.black,1));
              brett.add(feld[i][j]);
              feld[i][j].setOpaque(true);
              feld[i][j].setBackground(Color.lightGray);
              position[i][j]=0;
          }
        }
        start.addActionListener(this);                                     
    }
    public void actionPerformed(ActionEvent e) 
    {
        for(int i=0; i<a; i++)
            for(int j=0; j<a; j++)
                feld[i][j].setText("");
        for(int i=0; i<a*a; i++)
        {
            Algorithmus.xWeg[i]=0;
            Algorithmus.yWeg[i]=0;           
        }
        Algorithmus.first=true;
        int x,y;
        String s;        
        s=""+coords.getText().charAt(0);
        x=Integer.parseInt(s);
        s=""+coords.getText().charAt(2);
        y=Integer.parseInt(s);

        /* Der Backtracking-Algorithmus wird aufgerufen
         * Wenn das Springerproblem gelöst ist wird die Lösung ausgegeben
         */ 
        if(Algorithmus.solve(x,y,1)==true)
        {
            for(int i=0; i<a*a; i++)
                feld[Algorithmus.xWeg[i]][Algorithmus.yWeg[i]].setText(""+i);                     
            for(int i=0; i<a; i++)
                for(int j=0; j<a; j++)
                {
                    if(feld[i][j].getText().equals(""))
                        feld[i][j].setText("36");
                    if(feld[i][j].getText().equals("1")||feld[i][j].getText().equals("36"))
                        feld[i][j].setForeground(Color.blue);
                }            
        }
        else
            coords.setText("Keine Lösung");
        for(int i=0; i<a; i++)
            for(int j=0; j<a; j++)
                position[i][j]=0;       
    }
    public static void main(String[] args)
    {
        Springerproblem sp = new Springerproblem();
        sp.setVisible(true);
    }   
}
Algorithmus.java:
Code:
package prog;

public class Algorithmus 
{
    //Feldgröße: 6*6
    static int a=6;
    // xWerte und yWerte speichern alle 8 möglichen Richtungen, 
    // in die sich der Springer bewegen kann 
    // Das erste paar (00) wird nur beim ersten Aufruf benötigt
    final static int[] xWerte = {0,-1,-2, 1, 2,-1,-2, 1, 2};
    final static int[] yWerte = {0, 2, 1,-2, 1,-2,-1, 2,-1};
    static int[] xWeg  = new int[a*a];
    static int[] yWeg  = new int[a*a];
    static boolean first=true;
    
    public static boolean solve(int x,int y, int num)
    {    
        int xNeu, yNeu,k;
        boolean solved;
        k=0;       
        
        do{        
            ++k;
            
            if(first==true) 
            {
                --k;
                first=false;
            }
            solved=false;
            
            //Neue Koordinaten
            xNeu=x+xWerte[k];
            yNeu=y+yWerte[k];
            
            //Ist der Zug gültig?
            if(xNeu>=0 && yNeu>=0 && xNeu<a && yNeu<a)
            {
                //Ist das Feld frei?
                if(Springerproblem.position[xNeu][yNeu]==0)
                {          
                    //Setze in das Feld
                    Springerproblem.position[xNeu][yNeu]=num;
                    xWeg[num-1]=x;
                    yWeg[num-1]=y;
                    
                    //Problem gelöst?
                    if(num<(a*a))
                    {
                        //Wenn Problem noch nicht gelöst: Rekursion
                        solved=solve(xNeu,yNeu,num+1);
                        //Wenn der Rekursionsschritt in eine Sackgasse
                        //geführt hat, wird er zurück genommen
                        if(solved==false)
                        {
                            Springerproblem.position[xNeu][yNeu]=0;
                        }
                    }    
                    else
                        solved=true;
                    
                }
            }  
        } while(solved==false && k<8);
        return solved;
    }
}
Gruß, Boar
Angehängte Dateien
Dateityp: zip Springerproblem.zip (6,0 KB, 167x aufgerufen)
Boar ist offline   Mit Zitat antworten
Alt 07.07.05, 11:50   #7 (permalink)
Moderator
 
Registriert seit: 12.02.02
sirphreak Leistung: Facit NTK
Likes: 0
Standard

ich hab auch noch was auf meiner Platte gefunden:

wobei das schachbrett einfach mit durchlaufenden nummern dargestellt wird,
die man wenn manwill auch per konvert() zurückwandeln kann.

start per: "start."

Code:
start :- schachbrett(X), springer(10,X,Los), write(Los).

schachbrett([ 1, 2, 3, 4, 5, 6, 7, 8,
             9,10,11,12,13,14,15,16,
            17,18,19,20,21,22,23,24,
            25,26,27,28,29,30,31,32,
            33,34,35,36,37,38,39,40,
            41,42,43,44,45,46,47,48,
            49,50,51,52,53,54,55,56,
            57,58,59,60,61,62,63,64]).



%springer(_,[],_).
springer(_,[],[]).

springer(Feld,Felder,[Feld|Weg]):-F is Feld-17, member(F,Felder), del(F,Felder,Felder2), springer(F,Felder2,Weg).
springer(Feld,Felder,[Feld|Weg]):-F is Feld+17, member(F,Felder), del(F,Felder,Felder2), springer(F,Felder2,Weg).


springer(Feld,Felder,[Feld|Weg]):-F is Feld-15, member(F,Felder), del(F,Felder,Felder2), springer(F,Felder2,Weg).
springer(Feld,Felder,[Feld|Weg]):-F is Feld+15, member(F,Felder), del(F,Felder,Felder2), springer(F,Felder2,Weg).


springer(Feld,Felder,[Feld|Weg]):-F is Feld-6, member(F,Felder), del(F,Felder,Felder2), springer(F,Felder2,Weg).
springer(Feld,Felder,[Feld|Weg]):-F is Feld+6, member(F,Felder), del(F,Felder,Felder2), springer(F,Felder2,Weg).


springer(Feld,Felder,[Feld|Weg]):-F is Feld-10, member(F,Felder), del(F,Felder,Felder2), springer(F,Felder2,Weg).
springer(Feld,Felder,[Feld|Weg]):-F is Feld+10, member(F,Felder), del(F,Felder,Felder2), springer(F,Felder2,Weg).

del(_,[],[]).
del(X,[X|T],L):- del(X,T,L),!.
del(X,[Y|Z],[Y|T]):- del(X,Z,T),!.
edit: sollte ich erwähnen das das prolog ist ?
sirphreak ist offline   Mit Zitat antworten
Alt 14.09.05, 13:13   #8 (permalink)
 
Registriert seit: 27.01.02
JoBbE Leistung: Facit NTK
Likes: 0
Standard

Also ich habe mich mal daran gemacht, VIM auszuprobieren und womit ginge das besser, als mit einem kleinen Prograemmchen?
Also habe ich hier herumgestoebert und mir das Springerproblem ausgesucht.
Selbstkritik: Der Algorithmus ist scheisse. Extrem schlecht. Er funktioniert zwar zuverlaessig, aber ist sowas von lahm.
Der rekursive Ansatz ist natuerlich wesentlich besser, aber irgendwie habe ich nicht daran gedacht beim Schreiben
Asche auf mein Haupt.
Draw() ist nur eine Hilfsfunktion, die ich zum debuggen benutzt habe, sie war ganz nuetzlich.
Das Beispiel akzeptiert Groessen von 1-9, das ist reine Willkuer. Der Algorithmus wuerde auch mit unendlich grossen Brettern funktionieren.
Nur halt auch ewig brauchen hihi

Naja, ich wollte den code trotzdem hier reinstellen. Geloeste Aufgabe ist geloeste Aufgabe.

Code:
#include <iostream>
#include <sstream>
#include <vector>
#include <map>
#include <stack>
#include <string>
using namespace std;

enum eState {EMPTY, CURRENT, VISITED, ERROR};
typedef pair<int, int> Pos;
typedef map<Pos, eState> PosStateMap;
typedef pair<Pos, Pos> Move;
typedef pair<Move, int> MoveBan;
typedef stack<MoveBan> MoveStack;

class Brett
{
	public: 
		Brett();
		~Brett();
		void SetSize(int iSize);
		int GetSize();
		void SetAt(int x, int y, eState state);
		void SetAt(Pos pNew, eState state);
		const eState GetAt(int x, int y);
		void SetCurrent(int x, int y);
		void SetCurrent(Pos pCurrent);
		void Draw();
		void FindSolution();

	protected:
		bool OnBoard(Pos pTest) const;
		bool OnBoard(int x, int y) const;
		bool ExEmpty();
		MoveBan BuildMoveBan( int x1, int y1, int x2, int y2, int ban);
		MoveBan NewMbFromLast(MoveBan &mbLast, Pos &pZiel);
		int mSize;
		Pos mCurrent;
		PosStateMap mStates;
		MoveStack mMoveHistory;

};

MoveBan Brett::BuildMoveBan( int x1, int y1, int x2, int y2, int ban)
{
	Pos pFrom(x1, y1), pTo(x2, y2);
	
	Move mvMove(pFrom, pTo);
	
	MoveBan mb(mvMove, ban);

	return mb;
}

MoveBan Brett::NewMbFromLast(MoveBan &mbLast, Pos &pZiel)
{
	return BuildMoveBan(mbLast.first.second.first,
				  mbLast.first.second.second,
				  pZiel.first, pZiel.second, 0);
}

bool Brett::ExEmpty()
{
	bool isEmpty = false;
	for( int i = 1; i <= mSize; ++i)
		for( int j = 1; j <= mSize; ++j)
			if( GetAt(i, j) == EMPTY )
				isEmpty = true;
	return isEmpty;
}

void Brett::FindSolution()
{
	/* Der Suchalgorithmus (Do-While-Schleife)
	 * 1) Auf moegliche Felder pruefen (auf Brett, nicht VISITED, kein BAN)
	 * 2) Keine vorhanden
	 * 3)	Leere Felder?
	 * 4)		Nein
	 * 5)			Erfolg!
	 * 6)			History ausgeben
	 * 7)		Ja
	 * 8) 			From (0, 0)? keine Loesung moeglich, abbrechen
	 * 9)			Feld zwischenspeichern
	 * 10)			Auf letztes Feld zurueckgehen
	 * 11) 			Gespeichertes Feld zur Banliste
	 * 12)			Naechste Schleife
	 * 13) Auf erstes moegliches Feld bewegen
	 * 14) Bewegung in History speichern	
	 */
	
	// Offsets fuer die moeglichen Felder
	map<int, Pos> pOffsets;
	pOffsets[0].first = 1;
	pOffsets[0].second = -2;
	pOffsets[1].first = 2;
	pOffsets[1].second = -1;
	pOffsets[2].first = 2;
	pOffsets[2].second = 1;
	pOffsets[3].first = 1;
	pOffsets[3].second = 2;
	pOffsets[4].first = -1;
	pOffsets[4].second = 2;
	pOffsets[5].first = -2;
	pOffsets[5].second = 1;
	pOffsets[6].first = -2;
	pOffsets[6].second = -1;
	pOffsets[7].first = -1;
	pOffsets[7].second = -2;

	bool bSolved = false;

	// Move History initialisieren
	MoveBan mbBuf = BuildMoveBan(-1, -1, mCurrent.first, mCurrent.second, 0);
	mMoveHistory.push( mbBuf);

	do
	{
		MoveBan mbTmp = mMoveHistory.top();
		int iBanLevel = mbTmp.second;

		// leere Felder vorhanden?
		if( !ExEmpty() )
		{
			bSolved = true;
			break;
		}
		
		// ersten moeglichen Zielpunkt finden.
		Pos pZiel;
		for(int i = (0+iBanLevel); i <= 7; ++i)
		{
		 pZiel.first = mCurrent.first + pOffsets[i].first;
		 pZiel.second = mCurrent.second + pOffsets[i].second;
		 if(OnBoard(pZiel) && GetAt(pZiel.first, pZiel.second) == EMPTY)
		 {
			 // Zielpunkt gefunden
			 // Banlevel updaten
			 mbTmp.second = i;
			 mMoveHistory.pop();
			 mMoveHistory.push(mbTmp);
			 
			 // bewegen
			 mMoveHistory.push( NewMbFromLast(mbTmp, pZiel) );
			 // und auch im Spielbrett bewegen
			 SetCurrent(mMoveHistory.top().first.second);
			 SetAt(mMoveHistory.top().first.first, VISITED);
			 // naechste Schleife!
			 break;
		 }	 
		 ++iBanLevel;
		}		
				
		if( iBanLevel >= 8)
		{
			// Aufgabe unloesbar?
			MoveBan mbTmp = mMoveHistory.top();
			Pos pNull(-1, -1);
			if( mbTmp.first.first == pNull )
			{
				// Startpunkt erreicht, Banlevel 8
				cout << "Die Aufgabe ist nicht loesbar.\n";
				break;
			}
			
			// alle Zielpunkte gebannt
			// -> Zurueck zum letzten Punkt, Banlevel erhoehen
			SetCurrent(mMoveHistory.top().first.first);
			mMoveHistory.pop();
			mbTmp = mMoveHistory.top();
			++mbTmp.second;
			mMoveHistory.pop();
			mMoveHistory.push(mbTmp);
		}
	} while (true);

	if( bSolved )
	{
		cout << "Juhu, geloest!" << endl << "Und so gehts:\n\n";
		// mMoveHistory umdrehen
		MoveStack msTmp;
		while( !mMoveHistory.empty() )
		{
			msTmp.push( mMoveHistory.top() );
			mMoveHistory.pop();
		}
		mMoveHistory = msTmp;

		// ...und ausgeben
		for( int i = 0; i < mSize; ++i)
		{
			for( int j = 0; j < mSize; ++j)
			{
				MoveBan mbTmp = mMoveHistory.top();
				cout << (char)(64+mbTmp.first.second.first);
				cout << mbTmp.first.second.second;
				cout << " ";
				mMoveHistory.pop();
			}
			cout << "\n\n";
		}	
	}
}

bool Brett::OnBoard(int x, int y) const
{
	if( x <= 0 || y <= 0 || x > mSize || y > mSize )
		return false;
	return true;
}

bool Brett::OnBoard(Pos pTest) const
{
	return OnBoard(pTest.first, pTest.second);
}

Brett::Brett()
{
	SetSize(1);
	SetCurrent(1, 1);
}

Brett::~Brett()
{
}

void Brett::SetSize(int iSize)
{
	if( iSize <= 0 )
		mSize = 1;
	mSize = iSize;

	Pos pTemp;
	
	//Brett initialisieren
	for( int i = 1; i <= iSize; ++i)
		for( int j = 1; j <= iSize; ++j)
		{
			pTemp.first = i;
			pTemp.second = j;
			mStates[pTemp] = EMPTY;
		}
}

int Brett::GetSize()
{
	return mSize;
}

void Brett::SetAt(int x, int y, eState state)
{
	if( OnBoard(x, y) )
	{
		Pos pTemp;
		pTemp.first = x;
		pTemp.second = y;
		mStates[pTemp] = state;
	}
}

void Brett::SetAt(Pos pNew, eState state)
{
	SetAt(pNew.first, pNew.second, state);
}

const eState Brett::GetAt(int x, int y)
{
	if( OnBoard(x, y) )
	{
		Pos pTemp;
		pTemp.first = x;
		pTemp.second = y;

		return mStates[pTemp];
	}
	return ERROR;
}

void Brett::SetCurrent(int x, int y)
{
	Pos pTemp;
	pTemp.first = x;
	pTemp.second = y;
	SetCurrent(pTemp);
}

void Brett::SetCurrent(Pos pCurrent)
{
	if( OnBoard(pCurrent) )
	{
		SetAt(mCurrent, EMPTY);
		mCurrent = pCurrent;
		SetAt(mCurrent, CURRENT);
	}
}

void Brett::Draw()
{
	cout << endl;
	for(int i = 0; i <= mSize; ++i)
	{
		for(int j = 0; j <= mSize; ++j)
		{


			switch( GetAt(j, i) )
			{
				case EMPTY:
				{
					cout << "_";
					break;
				}

				case CURRENT:
				{
					cout << "o";
					break;
				}

				case VISITED:
				{
					cout << "X";
					break;
				}

				case ERROR:
				default:
				{
						
					if( j == 0 && i > 0)
						cout << (i);

					if( j > 0 && i == 0)
						cout << (char)(64+j);

					if( j == 0 && i == 0 )
						cout << " ";
				}
			}

			cout << " ";
		}
		cout << endl;
	}
}

void GetDigit(string sLabel, int *iGet)
{
	string s;
	bool error;
	istringstream ins;

	while(true)
	{

		error = false;
		cout << sLabel << " : ";
		cin >> s;

		if( s.size() > 1)
			error = true;
		else
			if( !isdigit(s[0] ) )
					error = true;
		if(!error)
			break;	
	}
	ins.str(s);
	ins >> *iGet;
}

int main()
{
	int iGroesse = 0;
	
	Pos pStart;

	do
		GetDigit("Brettgroesse", &iGroesse);
	while (iGroesse <= 0);
	
	do
		GetDigit("Startposition(X)", &pStart.first);
	while (pStart.first <= 0 || pStart.first > iGroesse);
		
	do
		GetDigit("Startposition(Y)", &pStart.second);
	while (pStart.second <= 0 || pStart.second > iGroesse);	

	Brett myBrett;
	myBrett.SetSize(iGroesse);
	myBrett.SetCurrent(pStart);

	Pos pTemp;

	myBrett.FindSolution();

	return 0;
}
JoBbE ist offline   Mit Zitat antworten
Alt 14.09.05, 13:51   #9 (permalink)
 
Registriert seit: 22.12.04
kito Leistung: Facit NTK
kito eine Nachricht über ICQ schicken
Likes: 0
Standard

@boar
beindruckend nicht schlecht dein proggi...die Geschwindigkeit verlangsamt sich bei größerem Feld wahrscheinlich durch die Rekursion die du drinnen hast. (denk ich mir mal)

Edit
Hab jetzt mal schnell ein Algo zusammengeschrieben...noch dazu in C (schon lange nicht mehr programmiert). Da ich auf dem Firmenpc bin und natürlich kein Compiler zur Hand habe, hab ich den Code nur im Notepad aus dem Kopf geschrieben.
Meiner Meinung nach müsste es so funktionieren, kann aber ruhig sein, dass Syntaxfehler oder sonstige Bugs vorhanden sind. Finde im Moment nur nicht so die Zeit sonst würd ich's Zuhause compilieren...Also wer Lust hat...
(Müsste mal jemand kompilieren :])
Grüße!

Code:
#include <stdio.h>

#define field_x 6
#define field_y 6

int visited[field_x][field_y];  //0 = not visited; 1 = visited


void initVisited(){
	int x=0;
	int y=0;
	for(y=0; i<field_y;y++){
		for(x=0; j<field_x; y++){
			visited[x][y] = 0;
		}
	}
}

int isVisited(int x, int y){
	//return -1 = out of bounds
	if(x>field_x || x<0) || (y>field_y || y<0) return -1;
	return visited[x][y];
}

void processPos(int x, int y){
	if(visited[][]==1 || visited[][]==-1) return;
	printf("visited pos(" + x + ";" + y + ")\n");
	processPos(x+1,y-2);
	processPos(x+2,y-1);
	processPos(x+2,y+1);
	processPos(x+1,y+2);
	processPos(x-1,y+2);
	processPos(x-2,y+1);
	processPos(x-2,y-1);
	processPos(x-1,y-2);
}

int main(void){
	//startpositions
	int startX = 0;
	int startY = 0; 	
	processPos(startX,startY);
}
kito ist offline   Mit Zitat antworten
Alt 14.09.05, 15:21   #10 (permalink)
 
Registriert seit: 03.12.04
Boar Leistung: Facit NTK
Likes: 0
Standard

Zitat:
@boar
beindruckend smile nicht schlecht dein proggi...die Geschwindigkeit verlangsamt sich bei größerem Feld wahrscheinlich durch die Rekursion die du drinnen hast. (denk ich mir mal)
Dankeschön! Ja, der hohe Rechenaufwand hängt mit der Rekursion zusammen. Beschleunigen ließe sich das ganze mit verbesserter Heuristik, bzw. Breitensuche. Wen es interessiert: klick

Gruß, Boar
Boar ist offline   Mit Zitat antworten
Alt 13.05.06, 20:17   #11 (permalink)
 
Registriert seit: 13.05.06
lotec Leistung: Facit NTK
Likes: 0
Standard

hi, Leute! Ich find den Forum ziemlich cool. Bei unseren Klausuren ist es leider übrig, den Code auf Papier zu schreiben, und zwar in völlig unrealistischen Zeitrahmen, deswegen hab ich versucht, die Aufgabe um die Zeit auf stück Blatt zu lösen. Na ja, hat doch nicht ganz geklappt ohne Rechnereinsatz, aber hier der Code:
Code:
#include <stdio.h>
int* field;
int* resx;
int* resy;
int counter=0;
int max=0;
int i, j;
void init()
{
	int i;
	field=(int*)malloc(64*sizeof(int));
	resx=(int*)malloc(sizeof(int)*64);
	resy=(int*)malloc(sizeof(int)*64);
	for(i=0; i<64; i++)
		field[i]=0;
	
}
void func(int x, int y)
{
	resx[counter]=x;
	resy[counter]=y;
	counter++;
	if(counter==64)
		show();
/*	if(counter==63)
	{
		for(i=0; i<8; i++)
		{
			for(j=0; j<8; j++)
				if(field[j*8+i])
					printf("*");
				else
					printf("0");
				printf("\n");
		}
		printf("\n\n\n");
}*/
						
	if((x+1<=7&&y-2>=0)&&(!field[8*(x+1)+y-2]))
	{
		field[8*(x+1)+y-2]=1;
		func(x+1, y-2);
		field[8*(x+1)+y-2]=0;
	}
		
	if((x+2<=7&&y-1>=0)&&(!field[8*(x+2)+y-1]))
	{
		field[8*(x+2)+y-1]=1;
		func(x+2, y-1);
		field[8*(x+2)+y-1]=0;
	}	
	if((x+2<=7&&y+1<=7)&&(!field[8*(x+2)+y+1]))
	{
		field[8*(x+2)+y+1]=1;
		func(x+2, y+1);
		field[8*(x+2)+y+1]=0;
	}
	if((x+1<=7&&y+2<=7)&&(!field[8*(x+1)+y+2]))
	{
		field[8*(x+1)+y+2]=1;
		func(x+1, y+2);
		field[8*(x+1)+y+2]=0;
	}
	if((x-1>=0&&y+2<=7)&&(!field[8*(x-1)+y+2]))
	{
		field[8*(x-1)+y+2]=1;
		func(x-1, y+2);
		field[8*(x-1)+y+2]=0;
	}	
	if((x-2>=0&&y+1<=7)&&(!field[8*(x-2)+y+1]))
	{
		field[8*(x-2)+y+1]=1;
		func(x-2, y+1);
		field[8*(x-2)+y+1]=0;
	}	
	if((x-2>=0&&y-1>=0)&&(!field[8*(x-2)+y-1]))
	{
		field[8*(x-2)+y-1]=1;
		func(x-2, y-1);
		field[8*(x-2)+y-1]=0;
	}	
	if((x-1>=0&&y-2>=0)&&(!field[8*(x-1)+y-2]))
	{
		field[8*(x-1)+y-2]=1;
		func(x-1, y-2);
		field[8*(x-1)+y-2]=0;
	}
	counter--;
	
}
void show()
{
	int i;
	for(i=0; i<64; i++)
		printf("%c%d  ", 97+resx[i], resy[i]+1);
	printf("\n\n\n\n");
}
int main()
{
	init();
	func(0,0);
}
Ach ja, kennt ihr das ähnliche Acht Damen- Problem? Acht Damen auf Feld zu stellen, ohne dass sie sich schlagen. Fast dasselbe, wie Springer- Problem, aber- mehr Möglichkeiten, nach einer effektiven Lösung zu suchen.
lotec ist offline   Mit Zitat antworten
Alt 16.07.08, 19:04   #12 (permalink)
 
Registriert seit: 21.04.08
Ook! Leistung: Facit NTK
Likes: 0
Standard

Meine Java Lösung... CDW hat wieder geholfen

Code:
public class Knightproblem {

	public static void main(String[] args) {
		System.out.println(new Knightproblem().new Solver().getResultField());
	}

	class Solver {

		private int[][] result = null;
		private final int size = 6;
		private int[][] jumps = { {-1,2}, {-2,1}, {1,-2}, {2,1}, {-1,-2}, {-2,-1}, {1,2}, {2,-1} };
		
		public Solver() {
			this.doIt(0, 0, new int[size][size], 1);
		}

		private boolean doIt(int x, int y, int[][] visited, int jump) {
			if(jump == (visited.length*visited.length)) {
				visited[x][y] = jump;
				result = visited;
				return true;
			}

			for(int i=0; i<8; i++) {
				if((x+jumps[i][0]) > -1 && (y+jumps[i][1]) > -1 && (x+jumps[i][0]) < visited.length && (y+jumps[i][1]) < visited.length) {
					if(visited[x+jumps[i][0]][y+jumps[i][1]] == 0) {
						visited[x][y] = jump;
						if(doIt((x+jumps[i][0]), (y+jumps[i][1]), visited, jump+1))
							return true;
						visited[x][y] = 0;
					}
				}
			}
			return false;
		}

		public String getResultField(){
			String returnString = "";
			for(int[] row : result) {
				for(int col : row) {
					returnString += (col +"\t");
				}
				returnString += "\n";
			}
			return returnString;
		}

	}

}
Gibt nur ein einziges Feld zurück, ich habe noch eine erweiterte Version... da brauch er allerdings recht lange um ein Ergebnis zu finden, deshalb werde ich die hier nicht posten!

Gruß
Felix
Ook! ist offline   Mit Zitat antworten
Alt 28.01.09, 14:45   #13 (permalink)
 
Benutzerbild von Stein
 
Registriert seit: 10.10.05
Stein Leistung: Facit NTK
Stein eine Nachricht über ICQ schicken
Likes: 0
Standard

Ich habe das mal in Pytohn realiesiert:
Python   

Code:
#Man muss versuchen einen Spinger ueber das ganze Schachbrett laufen zu lassen ohne, dass er ein Feld 2x betritt
def jump(x,y, betreten, spruenge):
    global i
    i += 1
    #print spruenge
    #rechte Seite
    if(im_feld(x + 1,y - 2) and was_there(betreten, x + 1,y - 2) == False):
        jump(x + 1,y - 2, betreten + "(" + str(x + 1) + "|" + str(y - 2) + ")", spruenge + 1 )
    if(im_feld(x + 1,y + 2) and was_there(betreten, x + 1,y + 2) == False):
        jump(x + 1,y + 2, betreten + "(" + str(x + 1) + "|" + str(y + 2) + ")", spruenge + 1 )
    if(im_feld(x + 2,y - 1) and was_there(betreten, x + 2,y - 1) == False):
       jump(x + 2,y - 1, betreten + "(" + str(x + 2) + "|" + str(y - 1) + ")", spruenge + 1 )
    if(im_feld(x + 2,y + 1) and was_there(betreten, x + 2,y + 1) == False):
       jump(x + 2,y + 1, betreten + "(" + str(x + 2) + "|" + str(y + 1) + ")", spruenge + 1)
    #linke Seite
    if(im_feld(x - 1,y - 2) and was_there(betreten, x - 1,y - 2) == False):
        jump(x - 1,y - 2, betreten + "(" + str(x - 1) + "|" + str(y - 2) + ")", spruenge + 1 )
    if(im_feld(x - 1,y + 2) and was_there(betreten, x - 1,y + 2) == False):
        jump(x - 1,y + 2, betreten + "(" + str(x - 1) + "|" + str(y + 2) + ")", spruenge + 1 )
    if(im_feld(x - 2,y - 1) and was_there(betreten, x - 2,y - 1) == False):
       jump(x - 2,y - 1, betreten + "(" + str(x - 2) + "|" + str(y - 1) + ")", spruenge + 1 )
    if(im_feld(x - 2,y + 1) and was_there(betreten, x - 2,y + 1) == False):
       jump(x - 2,y + 1, betreten + "(" + str(x - 2) + "|" + str(y + 1) + ")", spruenge + 1)
    if(spruenge == 63):
        print betreten
        exit()
def im_feld(x,y):
    if (x <= 8) and (x >= 1) and (y <= 8) and (y >= 1):
        return True
    else:
        return False
def was_there(betreten, x, y):
    if "(" + str(x) + "|" + str(y) + ")" in betreten:
        return True
    else:
        return False

i = 1
for x in range(1,9,1):
    for y in range(1,9,1):
        print "Start:" + str(x) + "|" + str(y)
        jump(x,y,"(" +str(x)+ "|" + str(y )+ ")",0)

Weil die aber so unfassbar langsam ist werde ich vielleich auch noch mal was in Java versuchen.
__________________
Steinhagelvoll
Stein ist offline   Mit Zitat antworten
Alt 29.01.09, 00:26   #14 (permalink)
 
Registriert seit: 22.03.08
MontyPerl Leistung: Facit NTK
Likes: 0
Standard

Zitat:
Weil die aber so unfassbar langsam ist werde ich vielleich auch noch mal was in Java versuchen.
Java's not quite there yet, write in C.
Naja, das liegt hauptsächlich am stumpfen backtrack-Algo. Der ist hier halt richtig lahm.

Hab das mal in C gemacht:
springerproblem.c   
Code:
#include <stdio.h>
#include <stdlib.h>
#include "stackChar.h"

#define VISITED 1

typedef struct {
    int xdim, ydim;
    int **f;
    int **moves;
} field;

field *getField(int x, int y);
int isValidPos(field *f, int x, int y);
void *xmalloc(int size);
void printField(field *f, int currx, int curry);
void clearField(field *f);
int solve(field *f, stack s, int x, int y, int visited);

int main(int argc, char *argv[]) {
    if (argc != 3) {
        fprintf(stderr, "usage: %s <m> <n>\n", argv[0]);
        exit(EXIT_FAILURE);
    }
    int x, y;
    x = atoi(argv[1]);
    y = atoi(argv[2]);
    field *f = getField(x, y);
    stack solution = newStack(64);
    int success = solve(f, solution, 0, 0, 0);
    if (success) {
        clearField(f);
        while (!isEmptyStack(solution)) {
            y = popStack(solution);
            x = popStack(solution);
            f->f[y][x] ^= VISITED;
            printField(f, x, y);
        }
    }
    return success ? EXIT_SUCCESS : EXIT_FAILURE;
}

int solve(field *f, stack s, int x, int y, int visited) {
    f->f[y][x] ^= VISITED;
    pushStack(s, x);
    pushStack(s, y);
    visited++;
    if (visited == (f->xdim * f->ydim)) {
        return 1;
    }
    int i, newx, newy;
    for (i = 0; i < 8; i++) {
        newx = x + f->moves[i][0];
        newy = y + f->moves[i][1];
        if (isValidPos(f, newx, newy)) {
            if (solve(f, s, newx, newy, visited)) {
                return 1;
            }
        }
    }
    popStack(s);
    popStack(s);
    f->f[y][x] ^= VISITED;
    return 0;
}

void clearField(field *f) {
    int x, y;
    for (y = 0; y < f->ydim; y++) {
        for (x = 0; x < f->xdim; x++) {
            f->f[y][x] = 0;
        }
    }
}

void printField(field *f, int currx, int curry) {
    int x, y;
    printf("\n");
    for (x = 0; x < f->xdim; x++) {
        printf("--");
    }
    printf("\n");
    for (y = 0; y < f->ydim; y++) {
        for (x = 0; x < f->xdim; x++) {
            if (x == currx && y == curry) {
                printf("@ ");
            }
            else {
                printf("%s", f->f[y][x] & VISITED ? "o " : ". ");
            }
        }
        printf("\n");
    }
}

field *getField(int x, int y) {
    int *rows = xmalloc(x * y * sizeof(int));
    int **arr = xmalloc(y * sizeof(int *));
    int i, j;
    for (i = 0; i < y; i++) {
        arr[i] = &rows[i * x];
        for (j = 0; j < x; j++) {
            arr[i][j] = 0;
        }
    }
    field *f = xmalloc(sizeof(field));
    f->f = arr;
    f->xdim = x;
    f->ydim = y;
    /* these are the 8 movement possibilities
     * written in the form (xoffset, yoffset):
     * 2, 1; 2, -1; -2, 1; -2, -1;
     * 1, 2; -1, 2; 1, -2; -1, -2;
     */
    int *move = malloc(2 * 8 * sizeof(int));
    int **moves = malloc(8 * sizeof(int *));
    int xd, yd; /* x delta and y delta */
    i = 0;
    for (xd = -2; xd <= 2; xd++) {
        for (yd = -2; yd <= 2; yd++) {
            if (xd && yd && (abs(xd) != abs(yd))) {
                move[i*2] = xd;
                move[(i*2)+1] = yd;
                moves[i] = &move[i*2];
                i++;
            }
        }
    }
    f->moves = moves;
    return f;
}

int isValidPos(field *f, int x, int y) {
    if (x < 0 || y < 0 || x >= f->xdim || y >= f->ydim) {
        return 0;
    }
    else if (f->f[y][x] & VISITED) {
        return 0;
    }
    return 1;
}

void *xmalloc(int size) {
    void *ptr = malloc(size);
    if (ptr == NULL) {
        fprintf(stderr, "not enough memory\n");
        exit(EXIT_FAILURE);
    }
    return ptr;
}
Hier der char-Stack code:

stackChar.h   
Code:
#include <stdlib.h>
#include <stdio.h>

/* stackChar.h -- a simple char stack */

#define POP_EMPTY '\0'
/* this is the char to be returned
 * by pop() on an empty stack.
 */


typedef struct stack {
    char *arr;
    int pos;
    int size;
    int alloc;  /* chunks to be (re)allocated at once on stack growth */
} *stack;


stack newStack(int allocChunk);        /* "constructor" if you will */
void destroyStack(stack s);            /* destructor */

void pushStack(stack s, char c);
char popStack(stack s);
char topStack(stack s);


stack newStack(int allocChunk) {
    struct stack *s = malloc(sizeof(struct stack));
    char *arr = malloc(allocChunk);
    if (arr == NULL || s == NULL) {
        fprintf(stderr, "Couldn't allocate memory for new stack-object (newStack())\n");
        exit(EXIT_FAILURE);
    }
    s->arr = arr;
    s->pos = -1;
    s->alloc = allocChunk;
    s->size = s->alloc;
    return s;
}

void destroyStack(stack s) {
    free(s->arr);
    free(s);
    return;
}

void pushStack(stack s, char c) {
    if (s->pos == (s->size - 1)) {
        s->size += s->alloc;
        s->arr = realloc(s->arr, s->size);
        if (s->arr == NULL) {
            fprintf(stderr, "Couldn't reallocate memory for stack (pushStack())\n");
            exit(EXIT_FAILURE);
        }
    }
    s->pos++;
    s->arr[s->pos] = c;
    return;
}

char popStack(stack s) {
    if (s->pos == -1) {
        return POP_EMPTY;
    }
    char c = s->arr[s->pos];
    s->pos--;
    return c;
}

char topStack(stack s) {
    if (s->pos == -1) {
        return POP_EMPTY;
    }
    else {
        return s->arr[s->pos];
    }
}

int isEmptyStack(stack s) {
    if (s->pos == -1) {
        return 1;
    }
    return 0;
}

Für ein n * m Feld. Gibt zu jedem Schritt das entsprechende Feld aus. (Auch zu schritten, die nicht zum Ziel führen.)
Wenn man den printField-Aufruf aus der Lösungsfunktion rausnimmt, "schaff" er ein 8x8 Feld in knapp unter 6 Sekunden. (Ich wollte das eigentlich mit deinem python Script vergleichen, aber das hab ich nach 3 Minuten abgebrochen.) Mit dem printField Aufruf dauert das weeeeeeeeeesentlich länger. Wobei das Ausgeben des Feldes eh etwas sinnfrei ist, da schaut man dem Computer halt beim wild rumprobieren zu.
Ich schau mal, dass ich ne Version nachreiche, die nur den richtigen Lösungsweg (insofern denn einer gefunden wurde) ausgibt.

edit: done. Das braucht jetzt 7.5 Sekunden für ein 8x8 Brett und gibt die gefundene Lösung dann aus.

Hier mal die Ausgabe für ein 5x5 Brett:

Lösung für ein 5x5 Brett   
Code:
$ time ./springerproblem 5 5

----------
. . . . . 
. . . . . 
. . . . . 
. . . . . 
. . . . @ 

----------
. . . . . 
. . . . . 
. . . . . 
. . @ . . 
. . . . o 

----------
. . . . . 
. . . . . 
. . . . . 
. . o . . 
@ . . . o 

----------
. . . . . 
. . . . . 
. @ . . . 
. . o . . 
o . . . o 

----------
. . . . . 
. . . . . 
. o . . . 
. . o . . 
o . @ . o 

----------
. . . . . 
. . . . . 
. o . . . 
. . o . @ 
o . o . o 

----------
. . . . . 
. . . @ . 
. o . . . 
. . o . o 
o . o . o 

----------
. @ . . . 
. . . o . 
. o . . . 
. . o . o 
o . o . o 

----------
. o . . . 
. . . o . 
@ o . . . 
. . o . o 
o . o . o 

----------
. o . . . 
. . . o . 
o o . . . 
. . o . o 
o @ o . o 

----------
. o . . . 
. . . o . 
o o . . . 
. . o @ o 
o o o . o 

----------
. o . . . 
. . . o @ 
o o . . . 
. . o o o 
o o o . o 

----------
. o . . . 
. . . o o 
o o @ . . 
. . o o o 
o o o . o 

----------
. o . . . 
. . . o o 
o o o . . 
@ . o o o 
o o o . o 

----------
. o . . . 
. @ . o o 
o o o . . 
o . o o o 
o o o . o 

----------
. o . @ . 
. o . o o 
o o o . . 
o . o o o 
o o o . o 

----------
. o . o . 
. o . o o 
o o o . @ 
o . o o o 
o o o . o 

----------
. o . o . 
. o . o o 
o o o . o 
o . o o o 
o o o @ o 

----------
. o . o . 
. o . o o 
o o o . o 
o @ o o o 
o o o o o 

----------
. o . o . 
@ o . o o 
o o o . o 
o o o o o 
o o o o o 

----------
. o @ o . 
o o . o o 
o o o . o 
o o o o o 
o o o o o 

----------
. o o o . 
o o . o o 
o o o @ o 
o o o o o 
o o o o o 

----------
. o o o @ 
o o . o o 
o o o o o 
o o o o o 
o o o o o 

----------
. o o o o 
o o @ o o 
o o o o o 
o o o o o 
o o o o o 

----------
@ o o o o 
o o o o o 
o o o o o 
o o o o o 
o o o o o 

real    0m0.009s
user    0m0.003s
sys     0m0.003s



edit2:
Hab mal ein kleines perlscript geschrieben, mit dem man sich die Ausgabe animiert ausgeben lassen kann:
springerAnimat0r.pl   
Code:
#!/usr/bin/env perl
use strict;
use warnings;

my $idleness = shift || .25;
my $clearstr = `clear`;

while (my $line = <STDIN>) {
    if ($line =~ /^-/) {
        select undef, undef, undef, $idleness;
        print $clearstr;
    }
    else {
        print $line;
    }
}
Auf windows muss man aus dem `clear` ein `cls` machen. (Afaik...)
Der input wird von stdin genommen und die Zeit in Sekunden (floats sind möglich) zwischen einzelnen Frames wird als erstes Argument genommen (oder default auf 0.25 gesetzt).
Mögliche Aufrufe:
Code:
$ ./springerproblem 10 10 > foo
$ ./springerAnimat0r.pl .5 < foo
$ # oder direkt durch die pipe:
$ ./springerproblem 5 5 | ./springerAnimat0r.pl .15
Enjoy the show.
MontyPerl ist offline   Mit Zitat antworten
Alt 04.02.09, 19:43   #15 (permalink)
Senior Member
 
Registriert seit: 03.09.05
Lesco Leistung: Facit NTK
Likes: 0
Standard

Zitat:
..write in C.
Das halte ich in 90% der Fälle für unnötig, umständlich und fehleranfällig(wobei Java auch nicht viel besser ist).

Hier eine Lösung in Haskell:
code   

Code:
import Control.Monad.ST
import Control.Monad.Cont
import Control.Applicative
import Data.Array.ST
import Data.Ix
import Data.List
import Data.Ord
import System.Environment

type Pos = (Int,Int)
type Board s = STUArray s Pos Int
type BoardAction r s a = ContT r (ST s) a

validMoves :: Board s -> Pos -> BoardAction r s [Pos]
validMoves b = sortWith (fmap length . valids) <=< valids
    where sortWith f l = map fst <$> sortBy (comparing snd) <$> mapM (\x -> (,) x <$> f x) l
          valids (x,y) = do
            bs <- lift $ getBounds b
            filterM (free b) [(x',y') | (dx,dy) <- [(1,2),(2,1)]
                             , x' <- [x-dx,x+dx], y' <- [y-dy,y+dy]
                             , inRange bs (x',y')]

free :: Board s -> Pos -> BoardAction r s Bool
free b p = (0==) <$> lift (readArray b p)

set :: Board s -> Pos -> Int -> BoardAction r s ()
set b p k = lift $ writeArray b p k

solve :: Board s -> Pos -> Int -> (String -> BoardAction r s ()) -> BoardAction r s ()
solve b pos k exit = lift (getBounds b) >>= \(_,(n,m)) -> do
  when (k > n*m) $ exit =<< printBoard b
  vms <- validMoves b pos
  forM_ vms $ \pos' -> set b pos' k >> solve b pos' (k+1) exit >> set b pos' 0

printBoard :: Board s -> BoardAction r s String
printBoard b = lift (getBounds b) >>= \(_,(n,m)) -> do
  let max = ceiling . logBase 10 . fromIntegral $ n*n + 1
      pad i = let s = show i in replicate (max-length s) ' ' ++ s
  lst <- mapM (mapM $ lift . readArray b) [[(i,j) | j <- [1..m]] | i <- [1..n]]
  return . unlines . map (unwords . map pad) $ lst

runIt :: Pos -> Pos -> IO ()
runIt size start = putStrLn <=< stToIO . flip runContT return $ do
                     b <- lift $ newArray ((1,1),size) 0
                     set b start 1
                     callCC $ \exit -> solve b start 2 exit >> fail "no solution"

main = map read <$> getArgs >>= \(size:start:[]) -> runIt size start

Schafft ein 160x160 Feld in ca 0.4s auf meinem Rechner(Core2Duo 2Ghz), wenn man es mit -O2 oder -O3 kompiliert(ghc 6.10.1). Aufruf mit: ./program "(n,m)" "(startx,starty)" (Beginnend bei 1). Die Geschwindigkeit kommt durch eine verbesserte Heuristik, die von einem Feld aus zuerst die Felder versucht, die die wenigsten gültigen Nachfolgefelder haben.

Beispiel-Ausgabe für ein 8x8-Feld:
ausgabe   

Code:
 1 16 59 34  3 18 21 36
58 33  2 17 60 35  4 19
15 54 57 62 43 20 37 22
32 63 46 53 56 61 42  5
49 14 55 64 47 44 23 38
28 31 48 45 52 41  6  9
13 50 29 26 11  8 39 24
30 27 12 51 40 25 10  7
Lesco ist offline   Mit Zitat antworten
Antwort
   
- Anzeige -

Werbung ist gerade online    

[HaBo] » Software Home » Code Kitchen » Programmieraufgaben » Springerproblem
Themen-Optionen
Ansicht

Forumregeln
Es ist Ihnen nicht erlaubt, neue Themen zu verfassen.
Es ist Ihnen nicht erlaubt, auf Beiträge zu antworten.
Es ist Ihnen nicht erlaubt, Anhänge hochzuladen.
Es ist Ihnen nicht erlaubt, Ihre Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks sind aus
Pingbacks sind aus
Refbacks sind aus


Ähnliche Themen
Thema Autor Forum Antworten Letzter Beitrag
Springerproblem Nornagest Programmieraufgaben 16 19.04.04 16:20


1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61