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.
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 );
}
}
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 ;)
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).
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 ;)
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);
}
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 :)
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);
}
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:
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.
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.
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.
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).
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...
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von Corpsegrinder am .
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
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von Floste am .
wenn statt ReadAllLinesReadLines 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!"
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 :D
Also meine neue Aufgabe:
Zitat von dem neuem Aufgabensteller
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 Drill Into .NET Framework Internals to See How the CLR Creates Runtime Objects 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
Dieser Beitrag wurde 6 mal editiert, zum letzten Mal von zommi am .
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.)
Dieser Beitrag wurde 2 mal editiert, zum letzten Mal von Floste am .
Projekte:Jade, HttpSaver
Zum Rechtschreiben gibts doch schon die Politiker. Aber die bauen auch nur mist!
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.
Dieser Beitrag wurde 2 mal editiert, zum letzten Mal von Floste am .
Projekte:Jade, HttpSaver
Zum Rechtschreiben gibts doch schon die Politiker. Aber die bauen auch nur mist!
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:
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!
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"
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;
}
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 :D ...
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;
}
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"