Laden...

Das Programmier-Spiel: nette Übungsaufgaben für zwischendurch

Letzter Beitrag vor 3 Jahren 762 Posts 773.800 Views

Hallo Gü,

Sodenn. Eine Kleinigkeit ist noch: Für die Eingabedaten...


var dataSource = new[]
{
	new Container { Date = new DateTime(2009,1,1),Value = "Januar '09" },
	new Container { Date = new DateTime(2010,1,1),Value = "Januar '10" },
	new Container { Date = new DateTime(2010,1,1),Value = "Januar '10" }
};

... ergibt dein Code:


LeftValue = "Januar '09" RightValue = null
LeftValue = "Januar '10" RightValue = "Januar '09"
LeftValue = "Januar '10" RightValue = null

Der zweite Jan10 hat kein Jan09. Das ein Eingabelement gleich dem Vorgängerelement sein kann, steht zwar in der Aufgabenstellung nur in Klammern, aber vll. bekommst du das noch schnell geändert.

Ansonsten: Sehr schön. Ist eine gültige Lösung. Du bist dran.

Besten Gruß,
dN!3L

Hallo Daniel,

Eine Kleinigkeit ist noch: Für die Eingabedaten...

Lässt sich durch entfernen von memo.Remove(...) lösen, allerdings wächst dann das Dictionary bei der unendlichen Eingabe 😉

Für die neue Aufgabe muss ich erstmal prüfen ob die noch im Verlaufe des Spiels gestellt worden ist - habe den Thread noch nicht lange verfolgt.

mfG Gü

Stellt fachliche Fragen bitte im Forum, damit von den Antworten alle profitieren. Daher beantworte ich solche Fragen nicht per PM.

"Alle sagten, das geht nicht! Dann kam einer, der wusste das nicht - und hat's gemacht!"

Hallo zusammen,

die nächste Aufgabe 😉


Gegeben sei folgender Code:
[CSHARP]
public class Aufgabe
{
	public IEnumerable<Ergebnis> Ermittle()
	{
		throw new NotImplentedException();
	}
}

public struct Ergebnis
{
	public int A;
	public int B;
	public int C;
}

[TestFixture]
public class AufgabeTest
{
	[Test]
	public void Ermittle_OK()
	{
		Aufgabe sut = new Aufgabe();

		List<Ergebnis> ergebnis = sut.Ermittle().ToList();
		Assert.AreEqual(1, ergebnis.Count);

		int a = ergebnis[0].A;
		int b = ergebnis[0].B;
		int c = ergebnis[0].C;

		Assert.IsTrue(a < b && b < c);
		Assert.AreEqual(c * c, a * a + b * b);
		Assert.AreEqual(1000, a + b + c);
	}
}
[/CSHARP]
Der Code für die Methode [tt]Ermittle[/tt] soll nun so vervollständigt werden dass der Test erfolgreich bestanden wird. Dabei soll zur Lösung jedoch kein brachialer Brute-Force verwendet werden (also möglichst wenig Iterationen ;-). Bei der Lösung auch [tt]Ergebnis[/tt] angeben.

Viel Spass!

mfG Gü

Stellt fachliche Fragen bitte im Forum, damit von den Antworten alle profitieren. Daher beantworte ich solche Fragen nicht per PM.

"Alle sagten, das geht nicht! Dann kam einer, der wusste das nicht - und hat's gemacht!"

Hallo Gü,

interessante Aufgabe. Kann man sogar ohne Programmieren lösen, indem man mal Wolfram fragt...
Hast du mal einen Richtwert für "möglichst wenig Iterationen"? Im Moment liege ich bei 83.167.
Wobei man den Test ja auch ohne eine einzige Iteration bestehen kann. Ergebnis ist ja konstant. 😉

Gruß,
dN!3L

Hallo,

ich hänge schon bei

Ergebnis: a: 200 b: 375 c: 425 Durchläufe: 25810025

🙁

Hallo Daniel,

Hast du mal einen Richtwert für "möglichst wenig Iterationen"?

Ich benötige < 5 Iterationen 😉

Wobei man den Test ja auch ohne eine einzige Iteration bestehen kann. Ergebnis ist ja konstant. 😉

Der Test ist nur dazu gedacht damit die Aufgabe erst daraus ermittelt werden muss - sonst empfand ich es als zu einfach 😉

Hallo Lennart,

das Ergebnis stimmt schon mal - aber zu viele Iterationen.

mfG Gü

Stellt fachliche Fragen bitte im Forum, damit von den Antworten alle profitieren. Daher beantworte ich solche Fragen nicht per PM.

"Alle sagten, das geht nicht! Dann kam einer, der wusste das nicht - und hat's gemacht!"

Hallo Gü,

Ich benötige < 5 Iterationen 😉

auch für andere Werte als 1000?

gruß

Darf das Verfahren schon nach dem ersten Fund aufhören oder sollen alle Tripel für a + b + c = 1000 gefunden werden? Oder gibt es gar nur eine Lösung?

As a man thinketh in his heart, so he is.

  • Jun Fan
    Es gibt nichts Gutes, außer man tut es.
  • Erich Kästner
    Krawutzi-Kaputzi
  • Kasperl

Hallo Lennart,

wenns >> 1000 dann ein paar mehr, aber nicht wesentlich mehr.

Hallo der-schlingel,

nachdem der Test nur 1 Lösung erlaubt kann abgebrochen werden 😉
Für a + b + c = 1000 gibts eh nur 1 Lösung.

mfG Gü

Stellt fachliche Fragen bitte im Forum, damit von den Antworten alle profitieren. Daher beantworte ich solche Fragen nicht per PM.

"Alle sagten, das geht nicht! Dann kam einer, der wusste das nicht - und hat's gemacht!"

Hi,

Kann man sogar ohne Programmieren lösen, indem man mal Wolfram fragt...

Das schließt sich doch nicht gegenseitig aus!
Daher - auch wenn nur so aus Spaß 😁


public IEnumerable<Ergebnis> Ermittle()
        {            
            string url = "http://api.wolframalpha.com/v1/query?appid=beta824g5&input=solve+a^2%2Bb^2%3Dc^2+and+a%2Bb%2Bc%3D1000+and+a%3Cb%3Cc+over+the+integers";
            var reg = new System.Text.RegularExpressions.Regex(@"a = (?<a>.*) and b = (?<b>.*) and c = (?<c>.*)");

            // Query an Wolfram Alpha absetzen
            // solve a^2+b^2=c^2 and a+b+c=1000 and a<b<c over the integers
            var xd = System.Xml.Linq.XDocument.Load(url);

            // ErgebnisTag finden
            var resultPod =
                (from item in xd.Descendants("queryresult").First().Descendants("pod")
                where (string)item.Attribute("id")=="Result"
                select item).First();
                        
            // Einzelne Ergebnisse als strings raussuchen "a=... and b=... and c=..."
            var solutions =
                from item in resultPod.Descendants("subpod")
                select item.Descendants("plaintext").First().Value;

            // Integer-Werte extrahieren
            return solutions.Select(s => 
                {
                    var g = reg.Match(s).Groups;
                    return new Ergebnis {
                        A = Int32.Parse(g["a"].Value), 
                        B = Int32.Parse(g["b"].Value),
                        C = Int32.Parse(g["c"].Value)
                    };
                });
                // Oder vor dem Semikolon noch ein 
                // .Where(e => e.A>0 && e.B>0 && e.C>0)
                // wenn man nur positive Lösungen sehen will
        }

beste Grüße
zommi

Hallo zommi,

interessant, aber die Ergebnisse stimmen nicht. Alleine schon deshalb da ich nicht das Ergebnis schreibe 😉

mfG Gü

Stellt fachliche Fragen bitte im Forum, damit von den Antworten alle profitieren. Daher beantworte ich solche Fragen nicht per PM.

"Alle sagten, das geht nicht! Dann kam einer, der wusste das nicht - und hat's gemacht!"

Jaaa, jetzt beschwer dich mal nich,
du hast ja nie geschrieben, dass du nur Lösungen mit a,b,c > 0 haben willst ;-P
Das Assert mit Count=1 deutet zwar darauf hin, aber explizit geht anders 😃

Negative Lösungen gibt er halt auch noch aus.
Aber dann pack eben noch noch ein


.Where(e => e.A>0 && e.B>0 && e.C>0)

an das return-Statement 😃

beste Grüße
zommi

wozu das where? schick einfach an wolfram alpha die bedingungen mit....

Hallo zommi,

du hast ja nie geschrieben, dass du nur Lösungen mit a,b,c > 0 haben willst

Das stimmt, aber es wurde nach 1 Lösung verlangt.

Assert.AreEqual(1, ergebnis.Count);

Aber egal...

Eigentlich hast du das Problem (mit der Where-Bedinung) gelöst und auch C#-Code gezeigt, aber es ist nicht so wie ich mir vorgestellt habe...

Wollt ihr noch weiter grübeln oder ist zommi dran?

mfG Gü

Stellt fachliche Fragen bitte im Forum, damit von den Antworten alle profitieren. Daher beantworte ich solche Fragen nicht per PM.

"Alle sagten, das geht nicht! Dann kam einer, der wusste das nicht - und hat's gemacht!"

aber es ist nicht so wie ich mir vorgestellt habe...
Wollt ihr noch weiter grübeln oder ist zommi dran?

Ja bitte eine ordentlich Lösung !
Also weitergrübeln!
Das war nur als Spaß, weil ich dN!3Ls Wolfram-Idee so gut fand =)

beste Grüße
zommi

wozu das where? schick einfach an wolfram alpha die bedingungen mit....

Das mag er bei mir irgendwie nicht 8o 🤔
Zuviele Bedingungen sind ihm wohl zu viel. Bei noch nehr Bedingung mehr oder nem "0<a<b<c" meckert er immer - bzw. liefert was ganz anderes, weil er die Frage dann nicht versteht. Daher das nachträgliche Rausfiltertern.
Aber siehs einfach als Quick and extradirty an - in jeder Hinsicht 😁

Das mag er bei mir irgendwie nicht

Nicht mit and, sondern mit Komma die Bedingungen trennen:
solve a2+b2=c^2 , a+b+c=1000 , 0<a<b<c over the integers

Ich habe zwar eine Lösung mit (momentan) 82.668 Iterationen (ohne Abbruch nach dem ersten Ergebnis), aber ich will erstmal den anderen den Vortritt lassen 😃
Los, Lennart und der-schlingel!

Hallo,

bin im Moment bei 176 Durchläufen. Weiter runter kom ich aber glaub nicht. Irgendwie fehlt mir die zündende Idee 😉.

gruß

Hallo Lennart,

Irgendwie fehlt mir die zündende Idee

Mathematik 😉
Irgendwie die Aufgabe umformen und dann kommt eine Ungleichung heraus. Somit müssen nur noch die Zahlen gesucht werden die Ungleichung erfüllen.

mfG Gü

Stellt fachliche Fragen bitte im Forum, damit von den Antworten alle profitieren. Daher beantworte ich solche Fragen nicht per PM.

"Alle sagten, das geht nicht! Dann kam einer, der wusste das nicht - und hat's gemacht!"

Hallo,

ne ich geb auf bin mit 176 auch zufrieden 😉.
Hier mal mein Ansatz (über pythagoreische Tripel):


int zahl = 12, a, b, c;
int durchläufe = 0;

for (int u = 1; u <= zahl / 50 + 2; u++)
{
    for (int v = 1; v < u; v++)
    {
        if (u * u + u * v == zahl / 2)
        {
            b = u * u - v * v;
            a = 2 * u * v;
            c = u * u + v * v;

            if (a > b)
            {
                int tmp = a;
                a = b;
                b = tmp;
            }

            if (a + b + c == zahl && c * c == a * a + b * b && a > 0 && b > a && c > b)
            {
                Console.Out.WriteLine("Ergebnis: a: " + a + " b: " + b + " c: " + c + " Durchläufe: " + durchläufe);
            }
        }
        durchläufe++;
    }
}

Hallo,

nachdem etwas Ruhe eingekehrt ist und **Lennart **die Aufgabe mit den wenigsten Iteration gemeister hat ist er für mich der Gewinner meines Spiels. Lennart darf also die nächste Aufgabe stellen.

Da ich geschrieben habe dass es mit 5 Iterationen möglich ist will ich euch die Lösung nicht vorenthalten.
Wie Lennart auch erkannte ist der Ansatz über Pythagoräische Tripel -> siehe angehängtes Bild.


public class Aufgabe
{
	public IEnumerable<Ergebnis> Ermittle()
	{
		Func<int, int, Ergebnis> erstelleErgebnis = (m, n) =>
			new Ergebnis
			{
				A = 2 * m * n,
				B = m * m - n * n,
				C = m * m + n * n
			};

		// 500 könnte noch angepasst werden...aber es wird eh abgebrochen ;-)
		for (int n = 1; n < 500; n++)	
		{
			// nur das positive Ergebnis ist interessant:
			double m1 = -n * 0.5 + Math.Sqrt(n * n * 0.25 + 500);
			if (m1 > n && ((int)m1 == m1))
			{
				int m = (int)m1;
				yield return erstelleErgebnis(m, n);
				Debug.WriteLine("Found at m1, n={0}, m={1}", n, m);
				yield break;
			}
		}
	}
}

mfG Gü

Stellt fachliche Fragen bitte im Forum, damit von den Antworten alle profitieren. Daher beantworte ich solche Fragen nicht per PM.

"Alle sagten, das geht nicht! Dann kam einer, der wusste das nicht - und hat's gemacht!"

Ich befürchte ich kenne kein Rätsel was den Anforderungen hier entspricht, euch also nicht total unterfordert 😉. Etwas aus dem Internet raussuchen find ich auch irgendwie doof deswegen würde ich sagen wer was interessantes auf Lager hat darf das einfach an meiner Stelle posten.

gruß

Hall zusammen,

ich hätte was kleines feines wenn Lennart verzichtet.

Gesucht ist die Funktion Machwas() aus folgendem Code:


public static void Main(string[] args)
		{
			var matrix = new List<List<double>> {
				new List<double> { 1.0, 1.1, 1.2, 1.3 },
				new List<double> { 2.0, 2.1, 2.2, 2.3 },
				new List<double> { 3.0, 3.1, 3.2, 3.3 },
				new List<double> { 4.0, 4.1, 4.2, 4.3 }
			};
			
			var sentence = "Dies ist ein Beispielsatz";
			
			var iter = matrix.Machwas(...);
			
			var iter2 = sentence.Machwas(...);
				
			foreach( var item in iter ) {
				Console.WriteLine( item );
			}
			
			Console.WriteLine("\n");
			
			foreach( var item in iter2 ) {
				Console.WriteLine( item );
			}
		}

welcher folgende Ausgabe liefert:

1
2
3
4
1,1
2,1
3,1
4,1
1,2
2,2
3,2
4,2
1,3
2,3
3,3
4,3

Dies
ist
ein
Beispielsatz

Ein paar Hinweise: Es ist offensichtlich eine Extension Method und es werden verschiedene Parameter übergeben um das Verhalten zu steuern - aber keiner der Parameter ist das Objekt auf das die Methode aufgerufen wird!

Ich hätte nun gerne den Code der Machwas() Methode und die Parameter mit denen er in den beiden Fällen aufgerufen wird. Die Aufgabe ist bissle was zum knobeln, technisch ist nichts arg kompliziertes dabei. Ich kann mir vorstellen das verschiedene Lösungen möglich sind, daher werde ich meine dann auch präsentieren (die wahrscheinlich nicht mal die schönstmögliche ist).

PS: Der Code ist übrigens einem Beispiel aus einem Buch nachempfunden. Für jemanden der dieses Buch hat und somit die Methode und die Parameter für die Matrix kennt, hoffe ich das die Parameter für den String noch ein bissle Spaß bringen 😉

Baka wa shinanakya naoranai.

Mein XING Profil.

Sollen es 2 extensionmethods werden (klingt fast zu einfach) oder soll es wie ich vermute nur eine werden (auch wenn ich mir noch nicht vorstellen kann wie eine extensionmethod sowohl auf string als auch auf list<list<double>> angewendet werden soll).

Hallo,

genau eine Extension Method, auch nicht überladen oder so. In beiden Fällen wird genau die gleiche Funktion aufgerufen. Das man sich das im ersten Moment vielleicht nicht vorstellen kann ist mit ein Reiz des Rätsels 😉

Baka wa shinanakya naoranai.

Mein XING Profil.

Hi,

hier mal meine Lösung... es geht sicher schöner, vor allem die matrixFunc, aber ich hab so lange kein C# mehr gemacht, dass ich gerade nur eine funktionierende Lösung haben wollte 😉


public static void Main (string[] args)
		{
			
			var matrix = new List<List<double>> {
                new List<double> { 1.0, 1.1, 1.2, 1.3 },
                new List<double> { 2.0, 2.1, 2.2, 2.3 },
                new List<double> { 3.0, 3.1, 3.2, 3.3 },
                new List<double> { 4.0, 4.1, 4.2, 4.3 }
            };

            var sentence = "Dies ist ein Beispielsatz";

            var iter = matrix.MachWas(matrixFunc);

            var iter2 = sentence.MachWas(stringFunc);

            foreach( var item in iter ) {
                Console.WriteLine( item );
            }

            Console.WriteLine("\n");

            foreach( var item in iter2 ) {
                Console.WriteLine( item );
            }
		}
		
		public static IList<String> matrixFunc(IEnumerable list) {
			if(!(list is List<List<double>>)) {
				throw new ArgumentException("Expected List<List<double>>.");
			}
			List<List<double>> l = (List<List<double>>)list;
			IList<String> tmp = new List<String>();
			for(int i = 0; i < l[0].Count; i++) {
				for(int j = 0; j < l.Count; j++) {
					tmp.Add(l[j][i].ToString(CultureInfo.CreateSpecificCulture("de-DE")));
				}
			}
			
			return tmp;
		}
		
		public static IList<String> stringFunc(IEnumerable str) {
			if(!(str is String)) {
				throw new ArgumentException("Expected string");
			}	
			return ((String)str).Split(' ');
		}
		
		public static IList<String> MachWas(this IEnumerable obj, Func<IEnumerable, IList<String>> f) {
			return f(obj);
		}

Hallo,

Dein Code erzeugt ohne Frage die gewünschte Ausgabe, da kann man nichts gegen sagen. Aber ehrlich gesagt hab ich mit was ganz anderem gerechnet und schön ist der Code nicht wirklich (was nicht heißen soll das meine Lösung zwangsweise schöner ist gg).

Die statischen Funktionen grad mit dem rumgecaste in der matrixFunct sind nicht wirklich schön. Und das die Funktion bei ner double Matrix strings zurückgibt ist erst recht nicht schön.

Ich weiß das das keine Bedingung war, aber wenn du es nicht sehr eilig mit einer neuen Aufgabe hast (die du ja aufgrund der korrekten Ausgabe ja stellen darfst), dann würde ich gerne eine Lösung haben die vollkommen typsicher ist - sprich es gibt keinen einzigen Cast und die Aufzählung die von der Machwas() Methode zurückkommt, besitzt als Typparameter im allgemeinen den Typ der Elemente die man aus dem Ursprungsobjekt anzeigt(sprich, hier strings und double). Und eine weitere, wichtige Forderung die zugegebener Maßen nicht aus den beiden Beispielen ersichtlich wird -> Die Klasse auf dessen Objekt die Methode Machwas angewendet wird, muss nicht IEnumerable implementieren! Sie muss keine der .Net Aufzählungstypen sein. Folgendes ist mit meiner Lösung auch Problemlos möglich:

			var iter3 = 1.Machwas(...)
				
			foreach( var item in iter3 ) {
				Console.WriteLine( item );
			}

Und er gibt als Ausgabe die Zahlen von z.B. 1-10 aus. Oder auch 1-100, je nachdem wie man die Parameter wählt. Die Funktion Machwas ist dabei nachwievor genau die selbe.

Ich hoffe du nimmst mir die weiteren Forderungen nicht böse und dich packt nochmal der Ehrgeiz, weil wichtige Punkte und mögliche Lösungen dieser, hast du in der Fragestellung ganz richtig erkannt 😃

Baka wa shinanakya naoranai.

Mein XING Profil.

Hi,

so, hier die angepasste Lösung (etwas schöner, aber die Methode für die Matrix gefällt mir immernoch nicht, geht sicher schöner, aber das ist ja hier nicht gefragt, sondern die Lösung für das allgemeine Problem 😉 ):


public static void Main (string[] args)
		{
			
			var matrix = new List<List<double>> {
                new List<double> { 1.0, 1.1, 1.2, 1.3 },
                new List<double> { 2.0, 2.1, 2.2, 2.3 },
                new List<double> { 3.0, 3.1, 3.2, 3.3 },
                new List<double> { 4.0, 4.1, 4.2, 4.3 }
            };

            var sentence = "Dies ist ein Beispielsatz";

            var iter = matrix.MachWas((List<List<double>> l ) => {
				IList<double> tmp = new List<double>();
				for(int i = 0; i < l[0].Count; i++) {
					for(int j = 0; j < l.Count; j++) {
						tmp.Add(l[j][i]);
					}
				}
				return tmp;	});
			
			
			
            var iter2 = sentence.MachWas((string s) => { return s.Split(' '); });

            foreach( var item in iter ) {
                Console.WriteLine( item );
            }

            Console.WriteLine("\n");

            foreach( var item in iter2 ) {
                Console.WriteLine( item );
            }
		}
		
		public static TReturn MachWas<TReturn, T>(this T obj, Func<T, TReturn> f) {
			return f(obj);
		}

Hallo,

ich hätt wahrscheinlich noch mehr vorgeben müssen um eine Lösung in die Richtung zu bekommen wie ich eigentlich gewollt hätte, aber was solls, dein Code löst ja wie gesagt zumindest die Probleme die ich als Beispiel genannt hatte 😃 Nächstmal werd ich noch genauer sein 😃 Dachte durch die Verwendung von foreach und zwei völlig unterschiedlichen Objekten kommt man auf die Idee nen eigenen Iterator zu schreiben .

Hier mal meine Lösung die ein wenig anders arbeitet als deine:

public static IEnumerable<TItem>
			MakeCustomIterator<TCollection, TCursor, TItem>(
				this TCollection collection,
				TCursor cursor,
				Func<TCollection, TCursor, TItem> getCurrent,
				Func<TCursor, bool> isFinished,
				Func<TCursor, TCursor> advanceCursor) {
					while( !isFinished(cursor) ) {
						yield return getCurrent( collection, cursor );
						cursor = advanceCursor( cursor );
					}
				}

Das ist die Erweiterungsmethode. Am Namen sieht man schon gleich worauf ich eigentlich hinaus wollte. Einen allgemein für alles mögliche einsetzbaren Iterator. Und dieser ist so allgemein gehalten damit man mit Angabe der passenden Parameter über alles iterieren oder ihn auch als Generator nutzen kann wie mein 3. Beispiel mit der 1 zeigen wird.

Mein Code für die Aufrufe sieht nun so aus:

var iter = matrix.MakeCustomIterator(
				// Cursor zum Merken der Position
				new int[] { 0, 0, int.MaxValue},
				// Aktuelles Element zurückgeben
				(coll, cur) => {
					cur[2] = coll.Count;
					return coll[cur[0]][cur[1]];
				},
				// Prüfen ob fertig
				(cur) => cur[0] >= cur[2] || cur[1] >= cur[2],
				// Nächstes Element wählen
				(cur) => { 
					if(++cur[0] >= cur[2]){
						cur[0] = 0;
						cur[1]++;
					}
					return new int[] { cur[0],cur[1],cur[2]};
				});
			
			var iter2 = sentence.MakeCustomIterator(
				// Cursor zum Merken der Position
				new int[] { 0, 0, int.MaxValue },
				// Aktuelles Element zurückgeben
				(coll, cur) => {
					cur[2] = coll.Length;
					var idx = coll.IndexOf(" ",cur[1]);
					return coll.Substring(cur[0],(cur[1] = idx > -1 ? idx : coll.Length)-cur[0]);
				},
				// Prüfen ob fertig
				(cur) => cur[1] >= cur[2],
				// Nächstes Element wählen
				(cur) => {
					return new int[] { cur[0]=++cur[1], cur[1], cur[2]};
				}
			);
			
			var iter3 = 1.MakeCustomIterator(
				// Cursor zum Merken der Position
				new int[] {1},
				// Aktuelles Element zurückgeben
				(coll, cur) => coll*cur[0],
				// Prüfen ob fertig
				cur => cur[0] > 10,
				// Nächstes Element wählen
				cur => new int[] { ++cur[0]} );

wie man sieht ist diese Lösung extrems generalisiert und egal was man macht, es werden immer die gleichen Schritte ausgeführt. Und das ist eigentlich das schöne an dieser Lösung. Es werden nicht komplett unterschiedliche Funktionen aufgerufen wie in deiner Lösung sondern man gibt nur die Funktionalität der einzelnen Schritte vor. Durch das Cursorobjekt hat man auch den Vorteil das keinerlei temporäre Variablen nötig sind um irgendwelche Zwischenergebnisse sich zu merken wie bei mit der List in der Matrix Funktion.

Es stellt sich natürlich die Frage unter welchen Umständen ein solch generalisierter Code überhaupt sinnvoll erscheint, oder ob es nicht einfach overengineered ist. Nichtsdestrotz zeigt meiner Meinung nach so ein Code wie mächtig hier Generics und anonyme Methoden zusammenwirken.

Das Beispiel wurde übrigend dem Buch "Accelerated C#" aus dem Apress Verlag entnommen. Dort ist es für die Matrix aufgeführt.

Baka wa shinanakya naoranai.

Mein XING Profil.

Ah, okay... da ich momentan fast nur noch funktional programmiere und da natürlich keine Iteratoren, geschweigedenn Schleifen verwende, bin ich garnicht auf die Idee gekommen es so zu lösen 😉

Eine neue Aufgabe muss ich mir noch überlegen, werde aber so schnell wie möglich eine stellen.

So, habe mir gerade eine hübsche Aufgabe überlegt.


Erstelle ein Banktransktionssystem, welches die Möglichkeit bietet Beträge von KontoA zu KontoB zu transferieren und die jeweiligen Kontostände abzufragen. Das ganze soll Threadsafe, aber OHNE Locking oder Synchronisation in dem Transaktionssystem erstellt werden. Es dürfen aber andere Strukturen benutzt werden, die schon Threadsafe sind (Listen, Queues...). Die Aufgabe ist nicht auf C# beschränkt, allerdings sollten keine Sprachen/Systeme benutzt werden, die STM bieten, wie z.B. Clojure oder Frameworks wie z.B. Akka für Scala.

Viel Spaß 😉

Schade, dass es hier nicht weitergeht, aber ich habe ehrlichgesagt auch keine lust obige aufgabe zu lösen.
Vielleicht fällt ja jemandem eine bessere ein.

Projekte:Jade, HttpSaver
Zum Rechtschreiben gibts doch schon die Politiker. Aber die bauen auch nur mist!

Ich finde du hast recht. Hiermit erkläre ich die obige Aufgabe für nicht mehr gültig, weil obsolet. Jemand darf nun eine neue Aufgabe stellen. Der Erste der postet hat gewonnen.

Hallo zusammen,

ich würde einen Schritt weiter gehen und sagen, dass der Thread grundsätzlich wieder frei für eine neue Aufgabe ist, wenn eine Woche seit dem letzten Beitrag vergangen ist (egal ob dieser letzte Beitrag nun eine Aufgabe, eine Nachfrage oder eine Lösung ist und egal ob die Lösung richtig oder falsch war, also einfach: eine Woche Inaktivität = neue Aufgabe erlaubt).

herbivore

Wenn Corpsegrinder noch eine Lösung für seine eigene Aufgabe hätte, wäre das auch nicht schlecht 😃

Also ich habe jetzt keine programmierte Lösung parat, aber es wäre relativ einfach gewesen. Alle Transaktionen kommen in eine Queue und werden nacheinander abgearbeitet, so ist kein Lock und keine Synchronisation nötig 😉.

edit: lesen des aktuellen Kontostandes geschieht natürlich direkt...

sorry aber eine Queue ist nicht Threadsafe und daher ist Synchronisation und Locking notwendig.

Wenn du meine Aufgabe gelesen hättest, dann wüsstest du, dass ich erlaubt habe Strukturen zu benutzen, die schon Threadsafe sind. Also auch eine Threadsafe Queue.

Hier aber nochmal eine Lösung, die ich eben erstellt habe:


import scala.actors.Actor
import scala.collection.immutable.HashMap

object Main {

  /**
   * @param args the command line arguments
   */

  def main(args: Array[String]) = {
    TransactionSystem ! ('create, "foo", 4000.)
    TransactionSystem ! ('create, "bar", 0.)
    TransactionSystem ! ('transfer, "foo", "bar", 2000.)
    println(TransactionSystem !? Tuple2('balance, "foo"))
    println(TransactionSystem !? Tuple2('balance, "bar"))
    TransactionSystem ! 'exit
  }

  object TransactionSystem extends Actor {
    start
    case class Account(val amount: Double)
    def act {
      act(HashMap[String, Account]())
    }
    def act(accs: HashMap[String, Account]): Unit = {
      react {
        case ('transfer, from: String, to: String, amount: Double)
          if(accs.contains(from) && accs.contains(to) &&
             accs(from).amount >= amount) => {
            act(accs.filter((acc) => acc != from && acc != to) ++
                HashMap(from -> Account(accs(from).amount - amount),
                        to -> Account(accs(to).amount + amount)))
        }
        case ('create, name: String, amount: Double) if(!accs.contains(name)) => act(accs ++ HashMap(name -> Account(amount)))
        case ('balance, name: String) if(accs.contains(name)) => reply(Some(accs(name).amount)); act(accs)
        case 'exit => exit
        case _ => println("Operation could not be completed."); act(accs)
      }
    }
  }

}

So, da immernoch keine neue aufgabe da ist, habe ich mal versucht eine zu machen (besonders kreativ is sie nicht, aber lösbar):

Aufgabe:
Schreibe ein programm, das das gemeinsame kgv (= kleinste gemeinsame vielfache) aller Zahlen in der liste im anhang in unter 10 sekunden findet. Das programm soll also genau eine zahl ausgeben.

Optional / Wünschenswert ist:
-lösen aufgabe in unter 1 sec
-möglichst simpler code
-eine gute nächste aufgabe in petto haben

Projekte:Jade, HttpSaver
Zum Rechtschreiben gibts doch schon die Politiker. Aber die bauen auch nur mist!

Mit .NET 4.0 würd ichs wie folgt machen:

using System;
using System.Numerics;
using System.IO;
using System.Linq;

public class LeastCommonMultiple
{
	public static void Main()
	{
		Console.Write(
			File
			.ReadAllLines("numbers.txt")
			.Select(s => BigInteger.Parse(s))
			.Aggregate((oldLCM, nextNumber) => 
				(oldLCM * nextNumber) / BigInteger.GreatestCommonDivisor(oldLCM, nextNumber)
			)
		);
	}
}

ergibt:

231448880682398148

beste Grüße
zommi

Hallo zommi,

wenn statt ReadAllLines ReadLines verwendet wird sollte es noch ein wenig schneller gehen da nicht zuerst die ganze Datei gelesen werden muss bevor mit Select fortgefahren werden kann. ReadLines enumeriert die Zeilen während ReadAllLines ein Array von Zeilen zurückgibt.

Sonst: Super Ansatz!

mfG Gü

Stellt fachliche Fragen bitte im Forum, damit von den Antworten alle profitieren. Daher beantworte ich solche Fragen nicht per PM.

"Alle sagten, das geht nicht! Dann kam einer, der wusste das nicht - und hat's gemacht!"

o.O, so war das nicht geplant, die funktion gibts in .net 3.5, das ich noch verwende ned.

Das ergebnis sieht aber richtig aus.

Projekte:Jade, HttpSaver
Zum Rechtschreiben gibts doch schon die Politiker. Aber die bauen auch nur mist!

Mhh.. aus Flostes Antwort konnte ich jetzt nicht herauslesen, wie zufrieden er mit der Lösung ist. Aber ich sehs mal als gelöst an 😄

Also meine neue Aufgabe:

Es wird Hacky:
Ihr sollt ein bischen Code schreiben, der aus einem gegebenen int[]-Array ein kleines Teilstück als neues int[]-Array extrahiert. Quasi ein SubArray. Aber so, dass Veränderungen am SubArray real im Ausgangsarray zu bemerken sind. Das SubArray muss also noch immer, speichermäßig, irgendwie, im großen Array "drin" liegen.

Ich gebe folgende Programmrahmen vor:

using System;  
using System.Collections.Generic;  
using System.Runtime.InteropServices;  
  
class Program  
{  
  static void Main(string[] args)  
  {  
  	// Zahlen Array erzeugen und im Speicher festpinnen  
  	int[] numberArray = new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13};  
  	GCHandle gch = GCHandle.Alloc(numberArray, GCHandleType.Pinned);  
  
  	// Aufruf der magischen Funktion, die ein .NET Array erzeugt,  
  	// das ein reales Unter-Array ist  
  	int[] subArray = SubArrayMaker.GetSubArray(numberArray);  
  
  	// Sicherstellen, dass das Array an Position 5 und 6 noch intakt ist.  
  	if (numberArray[5] != 5 || numberArray[6] != 6)  
  		return;  
  
  	// das Unter-Array komplett mit Nullen füllen  
  	lock(subArray) // nur aus Spaß gelockt, ihr seht schon warum ;)  
  		Array.Clear(subArray, 0, subArray.Length);  
  
  	// Überprüfen ob die 5te Stelle nun 0 ist, aber die 6te noch unverändert  
  	if (numberArray[5] == 0 && numberArray[6] == 6)  
  		Console.WriteLine("SUCCESS");  
  }  
}  
  
public class SubArrayMaker  
{  
  // ... ToDo: Implement! ... //  
}  
  

Ihr sollt der Klasse SubArrayMaker Leben einhauchen, sodass "SUCCESS" ausgegeben wird.
Man erkennt schon, dass das SubArray von seiner Länge her bis zum 6. Element des Ausgangsarrays gehen muss.

Kern der Aufgabe ist zu experimentieren, wie man ein managed .NET Objekt "konstruieren" kann, ohne jemals "new" aufgerufen zu haben und das dann auch noch in eine echte Objekt-Referenz zu pressen.

Das ganze ist tricky und erfordert wahrscheinlich unsafe-Pointer-Arithmetik. Man muss schon etwas über die CLR-Internas nachlesen und in ihren Eingeweiden rumfummeln 😉
Aber alles wichtige ist im Abschnitt "Object Instances" unter
>
zu finden.

PS: Ich empfehle ein 32-Bit System. Da ich selbst kein 64-Bit System verwende, kann ich nich garantieren, dass es dort auch eine Lösung gibt / machbar ist.

Ich wünsche viel Vergnügen und spannende Einsichten 😉
Und bei Fragen, einfach fragen.

beste Grüße
zommi


    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Modus: "+(IntPtr.Size*8)+"bit");
            // Zahlen Array erzeugen und im Speicher festpinnen
            int[] numberArray = new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13 };
            GCHandle gch = GCHandle.Alloc(numberArray, GCHandleType.Pinned);

            // Aufruf der magischen Funktion, die ein .NET Array erzeugt,
            // das ein reales Unter-Array ist
            int[] subArray = SubArrayMaker.GetSubArray(numberArray);

            // Sicherstellen, dass das Array an Position 5 und 6 noch intakt ist.
            if (numberArray[5] != 5 || numberArray[6] != 6)
                return;

            // das Unter-Array komplett mit Nullen füllen
            lock (subArray) // nur aus Spaß gelockt, ihr seht schon warum ;)
                Array.Clear(subArray, 0, subArray.Length);

            // Überprüfen ob die 5te Stelle nun 0 ist, aber die 6te noch unverändert
            if (numberArray[5] == 0 && numberArray[6] == 6)
                Console.WriteLine("SUCCESS");

            Console.ReadLine();
        }
    }

    public class SubArrayMaker
    {
        delegate IntPtr pRefToPtr(ref object reference);
        static pRefToPtr RefToPtr=MakeRefToPtr();

        private static pRefToPtr MakeRefToPtr()
        {
            DynamicMethod meth = new DynamicMethod("GetAddr", typeof(IntPtr), new Type[1] { typeof(object).MakeByRefType() },typeof(SubArrayMaker),true);
            ILGenerator gen= meth.GetILGenerator();
            gen.Emit(OpCodes.Ldarg_0);
            gen.Emit(OpCodes.Conv_I);
            gen.Emit(OpCodes.Ret);
            return (pRefToPtr)meth.CreateDelegate(typeof(pRefToPtr));
        }

        struct ArrayHeader
        {
            public IntPtr Syncblock1;
            public IntPtr TypeId;
            public IntPtr Length;
        }

        public static unsafe int[] GetSubArray(int[] numberArray)
        {
            ArrayHeader* oldArray = &(((ArrayHeader*)Marshal.UnsafeAddrOfPinnedArrayElement(numberArray, 0))[-1]);
            ArrayHeader* newArray=&(((ArrayHeader*)Marshal.UnsafeAddrOfPinnedArrayElement(numberArray, 5))[-1]);
            *newArray = *oldArray;
            newArray->Length = (IntPtr)1;

            object array = null;
            IntPtr* pArrayVar = ((IntPtr*)RefToPtr(ref array));
            *pArrayVar = (IntPtr)(&(newArray->TypeId));
            return (int[])array;
        }
    }

Geht unter 32 und 64 bit!
( aber auch nur, weil .net von m$ die letzten 4 bytes der arraylänge ignoriert, weil arrays mit 32 bit ints indiziert werden.)

Projekte:Jade, HttpSaver
Zum Rechtschreiben gibts doch schon die Politiker. Aber die bauen auch nur mist!

Sehr schön 👍

Meine Implementierung (für 32Bit) war:

public class SubArrayMaker
{
    public unsafe static int[] GetSubArray(int[] array)
    {
        fixed (int* ptr = array)
        {
            ptr[0] = 0;         // SyncBlock
            ptr[1] = ptr[-2];   // TypeInformation übernehmen
            ptr[2] = 3;         // Length

            return ConvertPointerToIntArrayReference(ptr + 1); 
        }
    }

    [StructLayout(LayoutKind.Sequential)]
    unsafe struct IntArrayHolder
    {
        public int[] array;
        public int* ptr;
    }

    unsafe static int[] ConvertPointerToIntArrayReference(int* ptr)
    {
        IntArrayHolder ah = new IntArrayHolder();
        (&ah.ptr)[-1] = ptr; // Referenz überschreiben
        return ah.array;
    }
}

Dann ist der Ball jetzt wohl wieder bei Floste 😉

Etwas skurril, aber ich stells mal trotzdem:

Schreibe ein programm, das folgendes tut:
wenn das programm ohne adminrechte läuft soll es nach diesen fragen. (runas)
danach soll es cmd.exe auf dem interactive service desktop starten.
Wichtig ist:
-das zu keinem zeitpunkt ein autostart installiert wird (darunter verstehe ich eine komponente/service/programm das beim systemstart automatisch geladen wird)
-der pc nicht neugestartet wird und weiterhin funktioniert
-am ende keinerlei listen- oder serviceeinträge übrigbleiben (wenn erstellt, müssen diese hinterher wieder entfernt werden.)
-keine dateien außerhalb des programmordners geschrieben werden. (am besten garkeine)
Außerdem soll das ganze am besten sofort und nicht erst nach einer minute passieren.

Es dürfen sämtliche .net und windows boardmittel benutzt werden, inklusive sämtlicher kommandozeilenprogramme.

Projekte:Jade, HttpSaver
Zum Rechtschreiben gibts doch schon die Politiker. Aber die bauen auch nur mist!

Hallo zusammen,

nachdem (mehr als) eine Woche ohne Antwort vergangen ist, ist entsprechende der Regeln die letzte Aufgabe (leider) obsolet und der Ball ja wieder frei. Ich nutze diesen Umstand für eine neue, hoffentlich populärere Aufgabe.

Es geht darum eine Methode zu schreiben, die ein Array von fünf Integers bekommt, das das Ergebnis von fünf Spielwürfelwürfen repräsentiert und als Ergebnis ein Array aller bei diesem Wurf möglichen Punkte nach den Kniffelregeln liefert.

Vorgegeben ist folgender Enum


public enum Scores
{
   Ones,            // Sum of Ones
   Twos,            // Sum of Twos
   Threes,          // Sum of Threes
   Fours,           // Sum of Fours
   Fives,           // Sum of Fives
   Sixes,           // Sum of Sixes
   ThreeOfAKind,    // Sum of all dice
   FourOfAKind,     // Sum of all dice
   FullHouse,       // 25
   SmallStraight,   // 30
   LargeStraight,   // 40
   Yahtzee,         // 50
   Chance           // Sum of all dice
}

der die Indexwerte für das zurückgelieferte Array definiert. Das zurückgelieferte Array hat also eine Länge von Enum.GetValues (typeof (Scores)).Length und enthält als Werte die Punkte, die durch den übergebenen Wurf in jeder der Kategorien erzielt werden können.

Die Signatur der Methode ist ebenfalls vorgegeben:

public static int [] GetPoints (int [] dice)

Getestet werden kann mit der folgenden Methode, die indirekt auch alle Zweifelsfälle bei der Interpretation von Ein- und Ausgabe der GetPoints-Methode klären sollte, insbesondere, dass die Werte der Würfelwürfe nicht als 1..6 sondern zerobased als 0..5 repräsentiert werden.


public static void Main (string [] astrArg)
{
   Random rand = new Random ();

   int [] dice = new int [5];

   for (int i = 0; i < dice.Length; ++i) {
      dice [i] = rand.Next (6); // also Werte von einschließlich 0 bis einschließlich 5
   }

   int [] points = GetPoints (dice);

   foreach (Scores score in Enum.GetValues (typeof (Scores))) {
      Console.WriteLine ("{0,15} {1}", score, points [(int)score]);
   }
}

Jetzt noch ein Beispiel. Das Eingabe-Array { 0, 4, 4, 0, 4 }, sprich zwei Einer und drei Fünfer (sic!), würde folgende Ausgabe produzieren:


         Ones 2
         Twos 0
       Threes 0
        Fours 0
        Fives 15
        Sixes 0
 ThreeOfAKind 17
  FourOfAKind 0
    FullHouse 25
SmallStraight 0
LargeStraight 0
      Yahtzee 0
       Chance 17

Es werden also alle Punkte angezeigt, die bei diesem Wurf möglich sind.

Es soll kein komplettes Kniffelspiel implementiert werden, sondern nur die eine wichtige Hilfsmethode GetPoints. Der Code meiner Implementierung dieser Methode ist knapp über 50 (normal formatierte) Zeilen lang. Die Aufgabe sollte also keine besondere Hürde darstellen, aber trotzdem Spaß machen!

herbivore

public static int [] GetPoints (int [] dice)  {
    int[] result = new int[Enum.GetValues(typeof(Scores)).Length];

    var getCount = new Func<int, int>((i) => dice.Where((d) => d == dice[i]).Count());

    Array.Sort(dice);

    result[(int)Scores.Ones] = dice.Where((d) => d == 0).Count() * 1;
    result[(int)Scores.Twos] = dice.Where((d) => d == 1).Count() * 2;
    result[(int)Scores.Threes] = dice.Where((d) => d == 2).Count() * 3;
    result[(int)Scores.Fours] = dice.Where((d) => d == 3).Count() * 4;
    result[(int)Scores.Fives] = dice.Where((d) => d == 4).Count() * 5;
    result[(int)Scores.Sixes] = dice.Where((d) => d == 5).Count() * 6;
    result[(int)Scores.ThreeOfAKind] = getCount(0) >= 3 || getCount(2) >= 3 || getCount(4) >= 3 ? dice.Sum((d) => d + 1) : 0;
    result[(int)Scores.FourOfAKind] = getCount(0) >= 4 || getCount(4) >= 4 ? dice.Sum((d) => d + 1) : 0;
    result[(int)Scores.FullHouse] = result[(int)Scores.ThreeOfAKind] > 0 ? (getCount(0) == 2 || getCount(4) == 2 ? 25 : 0) : 0;

    bool largeStraight = true;
    var num = dice[0];

    for (int i = 0; i < 5; i++) {
        largeStraight = largeStraight && (dice[i] == i + num);
    }

    result[(int)Scores.LargeStraight] = largeStraight ? 40 : 0;

    bool smallStraight = false;
    var arr = dice.Distinct().ToArray();

    if (arr.Length >= 4) {
        var slice = arr.Take(4).ToArray();
        
        num = slice[0];
        smallStraight = true;

        for (int i = 0; i < 4; i++) {
            smallStraight = smallStraight && (slice[i] == i + num);
        }
        
        if (!smallStraight && arr.Length == 5) {
            slice = arr.Skip(1).ToArray();
            smallStraight = true;
            num = slice[0];

            for (int i = 0; i < 4; i++) {
                smallStraight = smallStraight && (slice[i] == i + num);
            }
        }
    }

    result[(int)Scores.SmallStraight] = smallStraight ? 30 : 0;
    result[(int)Scores.Yahtzee] = getCount(0) == 5 ? 50 : 0;
    result[(int)Scores.Chance] = dice.Sum((d) => d + 1);

    return result;
}
`There are 10 types of people in the world: Those, who think they understand the binary system Those who don't even have heard about it And those who understand "Every base is base 10"`

Hallo TheBrainiac,

deine Lösung ist korrekt [EDIT=bis auf, dass Yahtzee auch als Fullhouse zählt (siehe Anmerkung von N1ls)[/EDIT]. Du bist mit der nächsten Aufgabe dran.

Hier zum Vergleich noch, wie ich mir das vorgestellt hatte [EDIT=korrigiert, dass Yahtzee auch als Fullhouse zählt[/EDIT]. Basierend auf dem Vorschlag in Kniffelspiel: Ermitteln, was geworfen wurde (z.B. Full House), ohne alle Kombinationen abzufragen habe ich zunächst ein Array aufgebaut, in dem für jede Augenzahl steht, wie oft die jeweilige Augenzahl gewürfelt wurde, um die anschließenden Berechnungen zu vereinfachen:


   public static int [] GetPoints (int [] dice)
   {
      int [] diceCounts = new int [6];
      int [] points = new int [Enum.GetValues (typeof (Scores)).Length];
      int    sumOfAllDice = 0;
      int    straight = 0;
      int    maxStraight = 0;
      bool   full = false;
      bool   house = false;

      for (int i = 0; i < dice.Length; ++i) {
         ++diceCounts [dice [i]];
         sumOfAllDice += dice [i] + 1;
      }

      for (int i = 0; i < diceCounts.Length; ++i) {
         points [i] = diceCounts [i] * (i + 1);
         if (diceCounts [i] > 0) { ++straight; }
         else { if (straight > maxStraight) { maxStraight = straight; } straight = 0; }
         if (diceCounts [i] == 2) { full = true; }
         if (diceCounts [i] >= 3) { points [(int)Scores.ThreeOfAKind] = sumOfAllDice; house = true; }
         if (diceCounts [i] >= 4) { points [(int)Scores.FourOfAKind] = sumOfAllDice; }
         if (diceCounts [i] >= 5) { points [(int)Scores.Yahtzee] = 50; points [(int)Scores.FullHouse] = 25; }
      }
      if (full && house) { points [(int)Scores.FullHouse] = 25; }
      if (straight > maxStraight) { maxStraight = straight; }
      if (maxStraight >= 4) { points [(int)Scores.SmallStraight] = 30; }
      if (maxStraight >= 5) { points [(int)Scores.LargeStraight] = 40; }
      points [(int)Scores.Chance] = sumOfAllDice;

      return points;
   }

herbivore

Hallo herbivore,

wenn ich mir deine Technik zum Ermitteln eines Full Houses ansehe, muss ich gerade über meinen eigenen Code lachen, den ich vor 1 1/2 Jahren dazu geschrieben habe 😄 ...
Die Kernidee war dabei folgende:

for (int index = 0; index < pipsOccurrences.Length; index++)
{
    int occurrence = pipsOccurrences[index];

    if (occurrence != 0)
    {
        occurrencesProduct *= occurrence;
    }
}

// The product of the occurrences of the non-zero values needs to be 6
// e.g. 4-4-4-6-6 is a valid Full House because we have 3 fours and 2 sixes
// => 2*3 = 6 (6 is only factorizable into 1*6 and 2*3; 1*6 cannot appear)
if (occurrencesProduct != 6)
{
    return false;
}

m0rius

Mein Blog: blog.mariusschulz.com
Hochwertige Malerarbeiten in Magdeburg und Umgebung: M'Decor, Ihr Maler für Magdeburg

Die neue Aufgabe:

Entwickle einen simplen Kompressions-Algorithmus!

Vorgegeben ist folgendes Snippet (Vollständige Vorlage siehe Anhang):

using System;
using System.Text;

public class Compression
{
    public static void Main() {
        string input = /*Gekürzt! Siehe Anhang!*/"";
        byte[] uncompressed = Encoding.ASCII.GetBytes(input);
        byte[] compressed = Compress(uncompressed);
        byte[] decompressed = Decompress(compressed);
        string output = Encoding.ASCII.GetString(decompressed);
        double ratio = (1d - (double)compressed.Length / (double)uncompressed.Length) * 100;
        bool equal = input == output;
        bool success = ratio > 10d && equal;
        
        Console.WriteLine("Uncompressed Length: {0}", uncompressed.Length);
        Console.WriteLine("Compressed Length: {0}", compressed.Length);
        Console.WriteLine("Decompressed Length: {0}", decompressed.Length);
        Console.WriteLine("Compression Ratio: {0:0.0000}%", ratio);
        Console.WriteLine("Input equals output: {0}", equal);
        Console.WriteLine("Successful: {0}", success);
        
        Console.ReadKey(true);
    }
    
    public static byte[] Compress(byte[] input) {
        // Hier der Kompressions-Algorithmus
    }
    
    public static byte[] Decompress(byte[] input) {
       // Hier der Dekompressions-Algorithmus
    }
}

Bedingungen:*Frameworks- / 3rd-Party-Klassen, die selbst Komprimierungsalgorithmen in irgend einer Form bereitstellen, sind verboten! *Die Kompressionsrate muss zum Erfolgreichen bestehen mindestens 10% betragen! *Die Kompression muss verlustfrei sein! (D.h. der Output von der Dekompressions-Methode muss gleich dem Input der Kompressions-Methode sein!)

Tipps:*Am Anfang war das Wort! *Ein Wörterbuch kann auch nicht schaden!

Gruß & Viel Spaß, Christian.

`There are 10 types of people in the world: Those, who think they understand the binary system Those who don't even have heard about it And those who understand "Every base is base 10"`