|
| » myCSharp.de Diskussionsforum |
|
|
|
|
Autor
 |
|
inflames2k
myCSharp.de-Mitglied
Dabei seit: 03.01.2010
Beiträge: 1.523
Entwicklungsumgebung: Visual Studio 2005 Standard Herkunft: Riesa
|
|
Um Exceptionhandling hab ich mich nun aber nicht gekümmert. War auch wenn ich mich nicht verlesen hab kein Teil der Aufgabe. :)
Hoffe das passt so.
C#-Code: |
class IMapClass : IMap<String, Object>
{
#region IMap<T,T> Member
List<String> _leftList = new List<String>();
List<Object> _rightList = new List<object>();
public void Add(String leftItem, Object rightItem)
{
if (!this._leftList.Contains(leftItem)
&& !this._rightList.Contains(rightItem))
{
this._leftList.Add(leftItem);
this._rightList.Add(rightItem);
}
else
{
throw new InvalidOperationException("Zuordnung nicht möglich, ein Objekt darf nur einmal vorkommen.");
}
}
public Object this[String item]
{
get
{
return this._rightList[_leftList.IndexOf(item)];
}
set
{
if(!_rightList.Contains(item))
this._rightList[_leftList.IndexOf(item)] = value;
else
throw new InvalidOperationException("Das Objekt existiert bereits bei einer anderen Zuordnung.");
}
}
public String this[Object item]
{
get
{
return this._leftList[_rightList.IndexOf(item)];
}
set
{
if(!_leftList.Contains(item)=
this._leftList[_rightList.IndexOf(item)] = value;
else
throw new InvalidOperationException("Das Objekt existiert bereits bei einer anderen Zuordnung.");
}
}
public bool Contains(String item)
{
return _leftList.Contains(item);
}
public bool Contains(Object item)
{
return _rightList.Contains(item);
}
public bool Remove(String item)
{
return this._rightList.Remove(_rightList[_leftList.IndexOf(item)]) && this._leftList.Remove(item);
}
public bool Remove(Object item)
{
return this._leftList.Remove(_leftList[_rightList.IndexOf(item)]) && this._rightList.Remove(item);
}
public void Clear()
{
this._leftList.Clear();
this._rightList.Clear();
}
public int Count
{
get { return this._leftList.Count; }
}
#endregion
}
|
Für Meinungen bin ich natürlich offen.
Dieser Beitrag wurde 2 mal editiert, zum letzten Mal von inflames2k am 04.05.2010 15:13.
|
|
04.05.2010 14:41
|
E-Mail |
Beiträge des Benutzers |
zu Buddylist hinzufügen
|
|
herbivore
myCSharp.de-Team (Admin)
Dabei seit: 11.01.2005
Beiträge: 47.492
Entwicklungsumgebung: csc/nmake (nothing is faster) Herkunft: Berlin
|
|
Hallo inflames2k,
| Zitat: |
| Um Exceptionhandling hab ich mich nun aber nicht gekümmert. War auch wenn ich mich nicht verlesen hab kein Teil der Aufgabe. :) |
nö, aber es war verlangt, dass Objekte nicht mehrfach vorkommen können. Das hast du zwar bei Add berücksichtigt, aber an anderen Stellen nicht.
Hallo edsplash,
wo ich eh gerade einen Beitrag schreibe:
| Zitat: |
| Man sollte dabei sofern möglich vermeiden auf .NET Klassen wie Dictionary<T>, HashSet<T> zurück zu greifen. |
Da hast du ja was schönes erreicht. inflames2k hat List <T>genommen (und wenn auch das nicht erlaubt gewesen wäre, dann vermutlich Array, irgendworauf wird man ja sinnvollerweise aufbauen). Dadurch ist deine Bedingung formal erfüllt. Aber was hast du erreicht? Der Code ist auch nicht länger oder komplizierter als wenn man Dictionary<> verwendet hätte, aber um Größenordnungen weniger performant.
herbivore
|
|
04.05.2010 14:55
|
E-Mail |
Beiträge des Benutzers |
zu Buddylist hinzufügen
|
|
herbivore
myCSharp.de-Team (Admin)
Dabei seit: 11.01.2005
Beiträge: 47.492
Entwicklungsumgebung: csc/nmake (nothing is faster) Herkunft: Berlin
|
|
Hallo inflames2k,
dein Code trifft es immer noch nicht. Du musst ja auf jeden Fall auch value prüfen. Außerdem muss es erlaubt sein, einem Objekt das bereits zugeordnete Objekt erneut zuzuordnen. Überlegt dir nochmal genau, welche Fälle alle auftreten können.
BTW: warum hast du die Klasse denn für konkrete Typen implementiert? Statt class IMapClass : IMap<String, Object> wäre Map<TLeft, TRight> : IMap<TLeft, TRight> deutlich sinnvoller gewesen (mal ganz abgesehen davon, dass Klassennamen keinen Präfix haben sollten, erst recht nicht den Präfix I).
herbivore
|
|
04.05.2010 15:15
|
E-Mail |
Beiträge des Benutzers |
zu Buddylist hinzufügen
|
|
inflames2k
myCSharp.de-Mitglied
Dabei seit: 03.01.2010
Beiträge: 1.523
Entwicklungsumgebung: Visual Studio 2005 Standard Herkunft: Riesa
|
|
Naja, stimmt so wohl auch wieder.
value hatte ich im Visual Studio geprüft wohl aber hier in der Änderung vergessen dies zu ändern.
Das mit der neu Zuordnung des selben Objektes stimmt so natürlich auch wieder. - Den Fall hatte ich nicht bedacht.
Konkrete Typen habe ich genommen, nachdem mein Compiler begann mir vorwürfe zu machen.
Nun aber die Volle und nun denk ich richtigere Variante:
C#-Code: |
class Map<TLeft, TRight> : IMap<TLeft, TRight>
{
#region IMap<TLeft,TRight> Member
List<TLeft> _leftList = new List<TLeft>();
List<TRight> _rightList = new List<TRight>();
public void Add(TLeft leftItem, TRight rightItem)
{
if (!_leftList.Contains(leftItem) && !_rightList.Contains(rightItem))
{
_leftList.Add(leftItem);
_rightList.Add(rightItem);
}
else
throw new InvalidOperationException("Ein Objekt kann nicht mehrfach zugeordnet werden.");
}
public TRight this[TLeft item]
{
get
{
return _rightList[_leftList.IndexOf(item)];
}
set
{
if(!_rightList.Contains(value) || _rightList[_leftList.IndexOf(item)].Equals(value))
_rightList[_leftList.IndexOf(item)] = value;
else throw new InvalidOperationException("Objekt ist bereits in der Zuordnung vorhanden.");
}
}
public TLeft this[TRight item]
{
get
{
return _leftList[_rightList.IndexOf(item)];
}
set
{
if (!_leftList.Contains(value) || _leftList[_rightList.IndexOf(item)].Equals(value))
_leftList[_rightList.IndexOf(item)] = value;
else throw new InvalidOperationException("Objekt ist bereits in der Zuordnung vorhanden.");
}
}
public bool Contains(TLeft item)
{
return _leftList.Contains(item);
}
public bool Contains(TRight item)
{
return _rightList.Contains(item);
}
public bool Remove(TLeft item)
{
return _rightList.Remove(_rightList[_leftList.IndexOf(item)]) && _leftList.Remove(item);
}
public bool Remove(TRight item)
{
return _leftList.Remove(_leftList[_rightList.IndexOf(item)]) && _rightList.Remove(item);
}
public void Clear()
{
_leftList.Clear();
_rightList.Clear();
}
public int Count
{
get { return _leftList.Count; }
}
#endregion
}
|
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von inflames2k am 04.05.2010 15:34.
|
|
04.05.2010 15:28
|
E-Mail |
Beiträge des Benutzers |
zu Buddylist hinzufügen
|
|
edsplash
myCSharp.de-Mitglied
Dabei seit: 19.04.2008
Beiträge: 390
Entwicklungsumgebung: VS2010
|
|
Hallo herbivore
| Zitat von herbivore: |
| Da hast du ja was schönes erreicht. inflames2k hat List <T>genommen (und wenn auch das nicht erlaubt gewesen wäre, dann vermutlich Array, irgendworauf wird man ja sinnvollerweise aufbauen). Dadurch ist deine Bedingung formal erfüllt. Aber was hast du erreicht? Der Code ist auch nicht länger oder komplizierter als wenn man Dictionary<> verwendet hätte, aber um Größenordnungen weniger performant. |
[offtopic]
Hehe, ich hatte gedacht, jemand würde es ohne Dictionary ähnlich performant hinkriegen ;) Mit dem Dictionary wird der Code allerdings weniger komplex, vorallem wenn man zwei davon verwendet -> Dictionary<TLeft, TRight> und Dictionar<TRight, TLeft>.
[/offtopic]
Hallo inflames2k
Deine Lösung scheint korrekt zu sein!
|
|
04.05.2010 15:51
|
E-Mail |
Beiträge des Benutzers |
zu Buddylist hinzufügen
|
|
TheBrainiac
myCSharp.de-Mitglied
Dabei seit: 17.12.2006
Beiträge: 767
Entwicklungsumgebung: VS 2010 Prof. Herkunft: /dev/null
|
|
Gnahh... Schon wieder zu langsam....
Gefragt war aber auch, die Implementierung ohne die Generischen Listen / Dictionaries aus System.Collections.Generic.
Hier ist meine Lösung:
C#-Code: |
public class Map<TLeft, TRight> : IMap<TLeft, TRight>
{
private TLeft[] m_Left = null;
private TRight[] m_Right = null;
private Boolean[] m_Used = null;
private Int32 m_Count = 0;
public Map()
: this(100) { }
public Map(Int32 startCapacity) {
m_Left = new TLeft[startCapacity];
m_Right = new TRight[startCapacity];
m_Used = new Boolean[startCapacity];
}
public void Add(TLeft leftItem, TRight rightItem) {
if (Contains(leftItem)) {
throw new ArgumentException("Item already added!", "leftItem");
}
if (Contains(rightItem)) {
throw new ArgumentException("Item already added!", "rightItem");
}
Int32 index = GetNextFreeIndex();
m_Used[index] = true;
m_Left[index] = leftItem;
m_Right[index] = rightItem;
m_Count++;
}
public TRight this[TLeft item] {
get {
Int32 idx = Find(item);
if (idx == -1) {
throw new KeyNotFoundException("Item not found!");
}
return m_Right[idx];
}
set {
if (Contains(value)) {
throw new ArgumentException("Item already added!", "value");
}
Int32 idx = Find(item);
if (idx == -1) {
Add(item, value);
} else {
m_Right[idx] = value;
}
}
}
public TLeft this[TRight item] {
get {
Int32 idx = Find(item);
if (idx == -1) {
throw new KeyNotFoundException("Item not found!");
}
return m_Left[idx];
}
set {
if (Contains(value)) {
throw new ArgumentException("Item already added!", "value");
}
Int32 idx = Find(item);
if (idx == -1) {
Add(value, item);
} else {
m_Left[idx] = value;
}
}
}
public Boolean Contains(TLeft item) {
return Find(item) != -1;
}
public Boolean Contains(TRight item) {
return Find(item) != -1;
}
public Boolean Remove(TLeft item) {
return Remove(Find(item));
}
public Boolean Remove(TRight item) {
return Remove(Find(item));
}
public void Clear() {
m_Used = new Boolean[m_Used.Length];
m_Left = new TLeft[m_Left.Length];
m_Right = new TRight[m_Right.Length];
}
public Int32 Count {
get {
return m_Count;
}
}
private Boolean Remove(Int32 idx) {
if (idx < 0 || idx > m_Used.Length || !m_Used[idx]) {
return false;
}
m_Used[idx] = false;
m_Left[idx] = default(TLeft);
m_Right[idx] = default(TRight);
m_Count--;
return true;
}
private Int32 GetNextFreeIndex() {
for (Int32 i = 0; i < m_Used.Length; i++) {
if (!m_Used[i]) {
return i;
}
}
EnlargeArrays();
return GetNextFreeIndex();
}
private void EnlargeArrays() {
Boolean[] tmpUsed = m_Used;
TLeft[] tmpLeft = m_Left;
TRight[] tmpRight = m_Right;
m_Used = new Boolean[tmpUsed.Length * 2];
m_Left = new TLeft[tmpLeft.Length * 2];
m_Right = new TRight[tmpRight.Length * 2];
tmpUsed.CopyTo(m_Used, 0);
tmpLeft.CopyTo(m_Left, 0);
tmpRight.CopyTo(m_Right, 0);
}
private Int32 Find(TLeft item) {
for (Int32 i = 0; i < m_Used.Length; i++) {
if (m_Used[i] && m_Left[i].Equals(item)) {
return i;
}
}
return -1;
}
private Int32 Find(TRight item) {
for (Int32 i = 0; i < m_Used.Length; i++) {
if (m_Used[i] && m_Right[i].Equals(item)) {
return i;
}
}
return -1;
}
}
|
Gruß, Christian.
Dieser Beitrag wurde 3 mal editiert, zum letzten Mal von TheBrainiac am 04.05.2010 16:21.
|
|
04.05.2010 16:13
|
Beiträge des Benutzers |
zu Buddylist hinzufügen
|
|
inflames2k
myCSharp.de-Mitglied
Dabei seit: 03.01.2010
Beiträge: 1.523
Entwicklungsumgebung: Visual Studio 2005 Standard Herkunft: Riesa
|
|
Gut, eine Aufgabe gibt es sobald mir etwas eingefallen ist. - Hatte zwar gerade einen Gedanken aber den müsst ich erstmal selbst für mich zusammen fassen.
Esseidenn dir fällt eine gute Aufgabe ein Schamese. :-) - Dann darfst du sie auch gern stellen.
Vermieden werden sollten Dictionary und HashSet, nicht alle Generics, aufgrund der Funktionalitäten die vom Dictionary Beispielsweise schon gegeben sind.
Wobei das nun auch unrelevant wäre. - Wie herbivore sagte, performant ist das nicht.
Dieser Beitrag wurde 2 mal editiert, zum letzten Mal von inflames2k am 04.05.2010 16:22.
|
|
04.05.2010 16:18
|
E-Mail |
Beiträge des Benutzers |
zu Buddylist hinzufügen
|
|
TheBrainiac
myCSharp.de-Mitglied
Dabei seit: 17.12.2006
Beiträge: 767
Entwicklungsumgebung: VS 2010 Prof. Herkunft: /dev/null
|
|
Hi @ All.
Nach Absprache mit inflames2k darf ich nun eine Aufgabe stellen.
Entwickle einen kleinen Parser & Interpreter für simple mathematische Formeln.
Er soll folgendes beherrschen: - Addieren, Subtrahieren, Multiplizieren und Dividieren von Integer-Literalen.
- Terme sollen mit Klammern zusammengefasst werden können.
- Der Interpreter soll das Ergebnis des eingegebenen Terms berechnen.
- Variablen, Funktionen und symbolische Konstanten brauchen nicht eingebaut werden.
Natürlich soll man seinen eigenen Parser/Interpreter schreiben. Parser-Generatoren, Vorgefertigte Interpreter, Scripting-Engines, Regex etc. sind nicht erlaubt. Ebenso gilt der Parser für mathematische Formeln nicht und darf auch nicht als Vorlage benutzt werden.
Gruß & Viel Spaß,
Christian.
Dieser Beitrag wurde 2 mal editiert, zum letzten Mal von TheBrainiac am 05.05.2010 17:47.
|
|
05.05.2010 08:27
|
Beiträge des Benutzers |
zu Buddylist hinzufügen
|
|
TheBrainiac
myCSharp.de-Mitglied
Dabei seit: 17.12.2006
Beiträge: 767
Entwicklungsumgebung: VS 2010 Prof. Herkunft: /dev/null
|
|
Hi @ All.
Ich habe auf den Rat von herbivore die Aufgabenstellung noch einmal angepasst.
Gruß, Christian.
|
|
05.05.2010 17:48
|
Beiträge des Benutzers |
zu Buddylist hinzufügen
|
|
MarsStein
myCSharp.de-Team (Moderation)
Dabei seit: 27.06.2006
Beiträge: 2.718
Entwicklungsumgebung: VS 2010, MonoDevelop, #Develop Herkunft: Trier -> München
|
|
Hallo,
ich glaub das müsste es bringen:
C#-Code: |
using System;
using System.Collections.Generic;
namespace TestApp
{
class Program
{
static double Calc(string input)
{
input = input.Trim();
if(input.Length > 0)
{
int open = input.LastIndexOf('(');
if(open >= 0)
{
int match = input.IndexOf(')',open);
if(match > open)
{
double partRes = Calc(input.Substring(open+1, match-open-1));
if(partRes != double.NaN)
{
return Calc(input.Remove(open, match-open+1).Insert(open, partRes.ToString()));
}
}
}
else
{
if(char.IsDigit(input[input.Length-1]))
{
int pos = input.IndexOf('+');
if(pos > 0)
{
return Calc(input.Substring(0,pos)) + Calc(input.Substring(pos+1));
}
pos = input.IndexOf('-');
if((pos > 0) && (Char.IsDigit(input[pos-1])))
{
return Calc(input.Substring(0,pos)) - Calc(input.Substring(pos+1));
}
pos = input.IndexOf('*');
if(pos > 0)
{
return Calc(input.Substring(0,pos)) * Calc(input.Substring(pos+1));
}
pos = input.IndexOf('/');
if(pos > 0)
{
return Calc(input.Substring(0,pos)) / Calc(input.Substring(pos+1));
}
double result;
if(double.TryParse(input, out result))
{
return result;
}
}
}
}
return double.NaN;
}
public static void Main(string[] args)
{
do
{
Console.WriteLine("Term eingeben:");
double result = Calc(Console.ReadLine());
Console.WriteLine("Ergebnis: " + result.ToString());
Console.WriteLine();
Console.WriteLine("Leertaste zum Beenden, andere Taste zum Fortfahren");
}while(Console.ReadKey().Key != ConsoleKey.Spacebar);
}
}
}
|
Edit: erlaubt sind nur die runden Klammern "()". Bei Fehleingaben müsste immer NaN zurückgegeben werden.
EDIT 2: Der Code hat nicht funktioniert, wenn innerhalb eines Klammerpaars eine negative Zahl herauskam. Ich habe die korrigierte Stelle oben markiert (Prüfung auf IsDigit vor einem '-')
Gruß, MarsStein
Dieser Beitrag wurde 3 mal editiert, zum letzten Mal von MarsStein am 05.05.2010 23:27.
|
|
05.05.2010 22:26
|
E-Mail |
Beiträge des Benutzers |
zu Buddylist hinzufügen
|
|
JAck30lena
myCSharp.de-Team (Admin)
Dabei seit: 01.10.2006
Beiträge: 11.393
Entwicklungsumgebung: Visual Studio 05/08/10 Prof.
|
|
das da:
C#-Code: |
if(partRes != double.NaN)
|
ist immer true. also kannst du es auch gleich weglassen, was dir dann immernoch das problem übriglässt, das partRes noch NaN sein könnte. aber fehleingaben sind ja keine bedingung. ich wollte es nur mal erwähnt wissen :-)
gib mal "-(10*5/6+(-5*7))" ein ;-)
Dieser Beitrag wurde 2 mal editiert, zum letzten Mal von JAck30lena am 06.05.2010 09:15.
|
|
06.05.2010 09:09
|
E-Mail |
Beiträge des Benutzers |
zu Buddylist hinzufügen
|
|
MarsStein
myCSharp.de-Team (Moderation)
Dabei seit: 27.06.2006
Beiträge: 2.718
Entwicklungsumgebung: VS 2010, MonoDevelop, #Develop Herkunft: Trier -> München
|
|
Hallo,
| Zitat von JAck30lena: |
| das da: if(partRes != double.NaN)ist immer true. |
Wenn Du den von Dir genannten Term eingibst, und zusätzlich innerhalb des if mal eine Konsolenausgabe machst, siehst Du, dass Du damit fasch liegst.
Trotzdem hast Du natürlich recht: da ist noch ein Fehler drin. Kümmere mich bald darum -> keine Zeit jetzt.
Gruß, MarsStein
|
|
06.05.2010 09:55
|
E-Mail |
Beiträge des Benutzers |
zu Buddylist hinzufügen
|
|
JAck30lena
myCSharp.de-Team (Admin)
Dabei seit: 01.10.2006
Beiträge: 11.393
Entwicklungsumgebung: Visual Studio 05/08/10 Prof.
|
|
sry... nein. ;-)
versuch mal:
C#-Code: |
string nurUmOptimierungenZuVermeiden = Console.ReadLine();
double d = double.NaN;
if(d == double.NaN) Console.WriteLine("hier ist double ein NaN \n" + nurUmOptimierungenZuVermeiden);
|
|
|
06.05.2010 10:02
|
E-Mail |
Beiträge des Benutzers |
zu Buddylist hinzufügen
|
|
MarsStein
myCSharp.de-Team (Moderation)
Dabei seit: 27.06.2006
Beiträge: 2.718
Entwicklungsumgebung: VS 2010, MonoDevelop, #Develop Herkunft: Trier -> München
|
|
Hallo Jack30lena,
du hast natürlich recht ;) habs jetzt auf double.IsNaN umgestellt, und das Problem mit "-(" dadurch behoben, dass es durch "-1*(" ersetzt wird:
C#-Code: |
using System;
namespace TestApp
{
class Program
{
static double Calc(string input)
{
input = input.Trim();
if (input.Length > 0)
{
int open = input.LastIndexOf('(');
if (open >= 0)
{
int match = input.IndexOf(')', open);
if (match > open)
{
double partRes = Calc(input.Substring(open + 1, match - open - 1));
if (!double.IsNaN(partRes))
{
return Calc(input.Remove(open, match - open + 1).Insert(open, partRes.ToString()));
}
}
}
else if (char.IsDigit(input[input.Length - 1]))
{
int pos = input.IndexOf('+');
if (pos > 0)
{
return Calc(input.Substring(0, pos)) + Calc(input.Substring(pos + 1));
}
pos = input.IndexOf('-');
if ((pos > 0) && (Char.IsDigit(input[pos - 1])))
{
return Calc(input.Substring(0, pos)) - Calc(input.Substring(pos + 1));
}
pos = input.IndexOf('*');
if (pos > 0)
{
return Calc(input.Substring(0, pos)) * Calc(input.Substring(pos + 1));
}
pos = input.IndexOf('/');
if (pos > 0)
{
return Calc(input.Substring(0, pos)) / Calc(input.Substring(pos + 1));
}
double result;
if (double.TryParse(input, out result))
{
return result;
}
}
}
return double.NaN;
}
static double Parse(String input) {
return Calc(input.Replace("-(", "-1*("));
}
public static void Main(string[] args)
{
do
{
Console.WriteLine("Term eingeben:");
double result = Parse(Console.ReadLine());
Console.WriteLine("Ergebnis: " + result.ToString());
Console.WriteLine();
Console.WriteLine("Leertaste zum Beenden, andere Taste zum Fortfahren");
} while (Console.ReadKey().Key != ConsoleKey.Spacebar);
}
}
}
|
sonst noch irgenwelche Fehler?
Gruß, MarsStein
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von MarsStein am 06.05.2010 15:24.
|
|
06.05.2010 10:21
|
E-Mail |
Beiträge des Benutzers |
zu Buddylist hinzufügen
|
|
TheBrainiac
myCSharp.de-Mitglied
Dabei seit: 17.12.2006
Beiträge: 767
Entwicklungsumgebung: VS 2010 Prof. Herkunft: /dev/null
|
|
Ich hab aber doch noch einen Fehler gefunden:
Gib mal (12+1)*2 ein... --> Heraus kommen sollte 26, aber es kommt NaN raus...
Gruß, Christian.
//EDIT Irgendie kommt bei mir immer wenn eine Klammer drin ist n. def. raus...
Dieser Beitrag wurde 4 mal editiert, zum letzten Mal von TheBrainiac am 06.05.2010 14:27.
|
|
06.05.2010 14:18
|
Beiträge des Benutzers |
zu Buddylist hinzufügen
|
|
Cat
myCSharp.de-Mitglied
Dabei seit: 25.10.2009
Beiträge: 453
|
|
Die Zeile
C#-Code: |
partRes = double.NaN;
|
ist wohl dafür verantwortlich (wahrscheinlich noch der Test wegen den NaN-Beiträgen vorher -)
|
|
06.05.2010 15:06
|
E-Mail |
Beiträge des Benutzers |
zu Buddylist hinzufügen
|
|
MarsStein
myCSharp.de-Team (Moderation)
Dabei seit: 27.06.2006
Beiträge: 2.718
Entwicklungsumgebung: VS 2010, MonoDevelop, #Develop Herkunft: Trier -> München
|
|
Hallo,
in der Tat ist es genau so wie Cat schrieb: Da ist mir 'ne Zeile vom Testen stehengeblieben. Ich editiere das gleich oben im Code und mache die Stelle dort auch kenntlich. Danach sollte aber alles laufen ;)
Die nächste Aufgabe gibt's dann heut abend.
Gruß, MarsStein
|
|
06.05.2010 15:19
|
E-Mail |
Beiträge des Benutzers |
zu Buddylist hinzufügen
|
|
TheBrainiac
myCSharp.de-Mitglied
Dabei seit: 17.12.2006
Beiträge: 767
Entwicklungsumgebung: VS 2010 Prof. Herkunft: /dev/null
|
|
Hallo, MarsStein.
Stimmt. Wenn ich die Zeile Raus nehme, funktioniert's einwandfrei.
Wie JAck30lena schon gesagt hat:
| Zitat von JAck30lena: |
| ich kann keine fehler mehr feststellen. wunderschöne lösung. respekt :-) |
Damit bist du dran!
Gruß, Christian.
|
|
06.05.2010 15:28
|
Beiträge des Benutzers |
zu Buddylist hinzufügen
|
|
MarsStein
myCSharp.de-Team (Moderation)
Dabei seit: 27.06.2006
Beiträge: 2.718
Entwicklungsumgebung: VS 2010, MonoDevelop, #Develop Herkunft: Trier -> München
|
|
Hallo,
| Zitat von JAck30lena: |
| wunderschöne lösung. respekt :-) |
danke dafür und für den Hinweis wegen NaN
Rekursion mal von hinten nach vorn und von innen nach außen
Dann mal die nächste Aufgabe:
erstellt ein Programm, das eine vom Benutzer wählbare Anzahl von Kugeln nach dem Prinzip des Galtonbretts auf einzelne Fächer verteilt. Die Anzahl der Stufen des Bretts soll ebenfalls vom Benutzer gewählt werden können (denkt daran, daß es ein Fach mehr als Stufen gibt).
Die dabei erzeugte Verteilung soll in einem Balkendiagramm (1 Balken je Fach) sinnvoll skaliert* ausgegeben werden. Die Balken sollen mit der entsprechenden Trefferzahl beschriftet werden.
Die Aufgabe ist mit der Ausgabe von waagerechten Balken auf der Konsole erfüllt.
Gruß, MarsStein
*Edit: Sinnvoll skaliert bezieht sich auf sinnvolle Eingabebereiche (die nicht geprüft werden müssen), bei denen die Anzahl der Kugeln viel größer als die Anzahl der Fächer ist, und die maximale Anzahl der Fächer im Bereich der Zeilenzahl der Konsole liegt.
Ich erwarte aber, daß die maximale Länge der Balken mit steigender Anzahl an Fächern mitwächst, die Kurve also halbwegs mitskaliert wird.
Dieser Beitrag wurde 3 mal editiert, zum letzten Mal von MarsStein am 06.05.2010 23:12.
|
|
06.05.2010 22:31
|
E-Mail |
Beiträge des Benutzers |
zu Buddylist hinzufügen
|
|
talla
myCSharp.de-Team (Moderation)
Dabei seit: 20.07.2003
Beiträge: 6.863
Entwicklungsumgebung: VS 2010 Herkunft: Esslingen
|
|
Hallo,
hier mal ne kurze Lösung von mir weil ich auch mal ne Aufgabe stellen möchte :)
C#-Code: |
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
namespace Galton {
class Program {
static void Main(string[] args) {
Console.Write("Geben Sie die Anzahl der Stufen an: ");
var stufen = Convert.ToInt32(Console.ReadLine());
Console.Write("Geben sie die Anzahl der Kugeln an: ");
var kugeln = Convert.ToInt32(Console.ReadLine());
Galton g = new Galton(stufen);
var bins = g.DropBalls(kugeln);
PrintResults(3, bins);
Console.ReadLine();
}
static void PrintResults(int startY, int[] bins) {
var scale = 75.0 / bins.Max();
for (int i = 0; i < bins.Length - 1; i++) {
var end = (int)(bins[i] * scale);
for (int j = 0; j < end; j++) {
Console.SetCursorPosition(j, startY + i*2);
Console.Write("x");
}
Console.SetCursorPosition(0, startY + i*2);
Console.Write(String.Format("{0} ",bins[i]));
}
}
}
public class Galton {
List<double> factors = new List<double>();
Random rand = new Random();
double sum;
public Galton(int level) {
Func<Decimal, Decimal> factorial = null;
Func<Decimal, Decimal, Decimal> binom = null;
factorial = (n) => (n == 0) ? 1 : n * factorial(n - 1);
binom = (n, k) => factorial(n) / (factorial(k) * factorial(n - k));
sum = Math.Pow(2.0, level);
foreach (var i in Enumerable.Range(0, level + 1)) {
factors.Add(Convert.ToDouble(binom(level, i)));
}
factors = factors.Aggregate(
new List<double>() { 0 },
(acc, item) => {
acc.Add(acc[acc.Count - 1] + item);
return acc;
}
, (acc) => acc).ToList();
}
public int[] DropBalls(int balls) {
int[] bins = new int[factors.Count];
for (int i = 0; i < balls; i++) {
var num = rand.NextDouble()*sum;
for (int j = 0; j < factors.Count; j++) {
if (num < factors[j]) {
bins[j-1]++;
break;
}
}
};
return bins;
}
}
}
|
| Zitat von MarsStein: |
*Edit: Sinnvoll skaliert bezieht sich auf sinnvolle Eingabebereiche (die nicht geprüft werden müssen), bei denen die Anzahl der Kugeln viel größer als die Anzahl der Fächer ist, und die maximale Anzahl der Fächer im Bereich der Zeilenzahl der Konsole liegt.
Ich erwarte aber, daß die maximale Länge der Balken mit steigender Anzahl an Fächern mitwächst, die Kurve also halbwegs mitskaliert wird. |
Ich erfülle diese Erwartung mit Absicht nicht - ob du die Aufgabe als gelöst erklärst ist dir überlassen. Der Grund ist einfach der, dass ich darin keinen Sinn sehe. Die Zeichenzahl in der Konsole pro Zeile ist so gering das man eh schon kaum gescheit skalieren kann. Wenn man bei wenigen Fächern die Balken kürzer macht, erkennt man bei Angabe der Kugeln in den Fächern gar nichts mehr.
|
|
08.05.2010 23:01
|
E-Mail |
Beiträge des Benutzers |
zu Buddylist hinzufügen
|
|
MarsStein
myCSharp.de-Team (Moderation)
Dabei seit: 27.06.2006
Beiträge: 2.718
Entwicklungsumgebung: VS 2010, MonoDevelop, #Develop Herkunft: Trier -> München
|
|
Hallo talla,
da die Skalierung ausdrücklich gefordert war, kann ich Deine Lösung leider so nicht durchgehen lassen
Diese eine Mutiplikation wirst Du schon noch einbauen müssen, wenn Du die nächste Aufgabe stellen möchtest...
Ich habe auch einen Grund dafür: Wenn die Balken an der Zeilenzahl skaliert werden, sind die Kurven von der Form her vergleichbarer, und die Gleichverteilung bei verschiedenen Eingaben läßt sich besser erkennen. Als Beispiel mal die Ausgabe meiner eigenen Lösung, ich denke das veranschaulicht das etwas:
Galtonbrett Simulation
Stufen: 8
Kugeln: 10000
35 -
297 -
1134 ----
2126 --------
2701 ---------
2252 --------
1088 ----
321 --
46 -
Stufen: 12
Kugeln: 100000
20 -
264 -
1627 -
5466 ----
12097 -------
19259 ------------
22551 -------------
19199 ------------
12198 --------
5361 ----
1630 -
299 -
29 -
Stufen: 16
Kugeln: 1000000
20 -
228 -
1835 -
8443 -
27608 ---
66411 ------
122927 -----------
174475 ----------------
196019 -----------------
175201 ----------------
121609 -----------
66909 ------
27857 ---
8379 -
1802 -
255 -
22 -
Gruß, MarsStein
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von MarsStein am 09.05.2010 00:43.
|
|
09.05.2010 00:16
|
E-Mail |
Beiträge des Benutzers |
zu Buddylist hinzufügen
|
|
talla
myCSharp.de-Team (Moderation)
Dabei seit: 20.07.2003
Beiträge: 6.863
Entwicklungsumgebung: VS 2010 Herkunft: Esslingen
|
|
Hallo,
hier die geänderte Ausgabefunktion:
C#-Code: |
static void PrintResults(int startY, int[] bins) {
var max = Convert.ToDouble(bins.Max());
var baseChars = 10.0;
var log = (int)Math.Log10(max);
for (int i = 0; i < log; i++) {
baseChars += 5.0;
}
var scale = baseChars / bins.Max();
var offset = 10;
for (int i = 0; i < bins.Length - 1; i++) {
var end = (int)(bins[i] * scale);
for (int j = 0; j < end; j++) {
Console.SetCursorPosition(offset + j, startY + i*2);
Console.Write("x");
}
Console.SetCursorPosition(0, startY + i*2);
Console.Write(bins[i]);
}
}
|
Wobei ich die Skalierung immer noch vollkommen irreführend finde. Gerade in deinem letzten Beispiel sieht man das gut. Sowohl das erste Fach mit 20, als auch das 4. mit 8443 Kugeln, werden mit jeweils nur einer Einheit dargestellt. Wenn man von ganz weit weg schaut, sieht man zwar die entstehende Binomialverteilung, aber die Kurve stimmt vorne und hinten nicht in der Darstellung (was natürlich an der Konsole liegt als Ausgabemedium).
|
|
09.05.2010 10:25
|
E-Mail |
Beiträge des Benutzers |
zu Buddylist hinzufügen
|
|
MarsStein
myCSharp.de-Team (Moderation)
Dabei seit: 27.06.2006
Beiträge: 2.718
Entwicklungsumgebung: VS 2010, MonoDevelop, #Develop Herkunft: Trier -> München
|
|
Hallo talla,
Über den SInn und Unsinn der Skalierung kann man sicherlich streiten, vor allem hast Du recht mit Deinen Aussagen:
| Zitat: |
| Gerade in deinem letzten Beispiel sieht man das gut. Sowohl das erste Fach mit 20, als auch das 4. mit 8443 Kugeln, werden mit jeweils nur einer Einheit dargestellt. |
und
| Zitat: |
| sieht man zwar die entstehende Binomialverteilung, aber die Kurve stimmt vorne und hinten nicht in der Darstellung |
Und ich hnbe recht , wenn ich behaupte, daß die Kurven wenn sie skaliert sind vom optischen Eindruck her leichter untereinander zu vergleichen sind.
Die Aufgabe ist jedenfalls mit der erweiterten Ausgabefunktion gelöst und Du bist dran
Gruß, MarsStein
|
|
09.05.2010 12:40
|
E-Mail |
Beiträge des Benutzers |
zu Buddylist hinzufügen
|
|
talla
myCSharp.de-Team (Moderation)
Dabei seit: 20.07.2003
Beiträge: 6.863
Entwicklungsumgebung: VS 2010 Herkunft: Esslingen
|
|
Okay,
ich hab ne kleine Implementierungsaufgabe bei der es mehr um Wissen geht, als irgend einen Standardalgorithmus zu implementieren.
Gegeben ist ein Stück Code names Add welcher eine Addition von 4 Werten übernehmen soll. Er soll dabei folgendermaßen aufgerufen werden können:
C#-Code: |
var erg = Add(1, 2, 3, 4);
var erg2 = Add.SomethingNice()(1)(2)(3)(4);
|
In beiden Variablen, erg und erg2 soll als Ergebnis die Summe der Argumente, also 10, stehen.
Nun die Frage: Wie müsste Add aussehen und wie SomethingNice? Wie nennt man das, was da passiert. Ist es vielleicht gar nicht möglich in C# sowas zu schreiben?
EDIT: Kleine Ergänzung (die im Prinzip auch ein, gar nicht mal so unbedeutender, Tipp ist):
Sowas soll auch möglich sein:
C#-Code: |
var tmp = Add.SomethingNice()(1)(3);
var erg3 = tmp(4)(2);
|
Ergebniss ist natürlich wieder die Summe der Argumente, also 10.
|
|
09.05.2010 17:26
|
E-Mail |
Beiträge des Benutzers |
zu Buddylist hinzufügen
|
|
Corpsegrinder
myCSharp.de-Mitglied
Dabei seit: 30.01.2007
Beiträge: 401
Entwicklungsumgebung: VS 2008 , .Net 3.5
|
|
Ich gehe zwar davon aus, dass du eigentlich eine Lösung in F# haben wolltest, da es aber ja auch Scala für die .Net Plattform gibt hab ich es mal in Scala gemacht:
Code: |
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
|
object Main {
/**
* @param args the command line arguments
*/
def main(args: Array[String]): Unit = {
println(Add(1,2,3,4))
val add5 = Add.somethingNice(2)(3) _
println(add5(2)(3))
}
}
object Add {
def apply(a: Int, b: Int, c: Int, d: Int) = somethingNice(a)(b)(c)(d)
def somethingNice(a: Int)(b: Int)(c: Int)(d: Int) = a + b + c + d
} |
|
|
|
09.05.2010 22:07
|
E-Mail |
Beiträge des Benutzers |
zu Buddylist hinzufügen
|
|
talla
myCSharp.de-Team (Moderation)
Dabei seit: 20.07.2003
Beiträge: 6.863
Entwicklungsumgebung: VS 2010 Herkunft: Esslingen
|
|
| Zitat von Corpsegrinder: |
| Ich gehe zwar davon aus, dass du eigentlich eine Lösung in F# haben wolltest |
Dann hätte ich was gesagt. Ich dachte die Frage danach, ob es in C# geht, deutet darauf hin, dass ich natürlich eine Lösung in C# möchte :) Daher kann ich deine Lösung so nicht gelten lassen (ich kann praktisch kein Scala, aber soweit ich deinen Code verstehe macht er schon prinzipiell das wonach ich gefragt habe, halt auf die Scala Art)
EDIT: Durch die Antwort ist ja praktisch schon verraten das es natürlich in C# geht - ich hätte neben der Lösung aber auch noch den Namen der Technik ( aber bitte beides zusammen, nur die Nennung des Namens würde die Lösung dann durch suchen im Inet trivial machen)
|
|
09.05.2010 22:36
|
E-Mail |
Beiträge des Benutzers |
zu Buddylist hinzufügen
|
|
Corpsegrinder
myCSharp.de-Mitglied
Dabei seit: 30.01.2007
Beiträge: 401
Entwicklungsumgebung: VS 2008 , .Net 3.5
|
|
Okay, ich wäre nie auf die Idee gekommen, dass C# currying kann ;-)
Hier mal die Lösung:
C#-Code: |
private static void Main(string[] args)
{
Func<int, int, int, int, int> Add = (a, b, c, d) => a + b + c + d;
Console.WriteLine(Add(1,2,3,4));
var tmp = Add.SomethingNice()(1)(2);
Console.WriteLine(tmp(3)(4));
}
public static Func<T1, Func<T2, Func<T3, Func<T4, T5>>>>
SomethingNice<T1,T2,T3,T4,T5> (this Func<T1,T2,T3,T4,T5> f)
{
return a => b => c => d => f(a, b, c, d);
}
|
|
|
09.05.2010 23:10
|
E-Mail |
Beiträge des Benutzers |
zu Buddylist hinzufügen
|
|
talla
myCSharp.de-Team (Moderation)
Dabei seit: 20.07.2003
Beiträge: 6.863
Entwicklungsumgebung: VS 2010 Herkunft: Esslingen
|
|
Kann es :)
Aber die Möglichkeiten die sich in C# durch die Einbindung von Eigenschaften funktionaler Sprachen bieten, sind in der Tat recht unbekannt. Ne Suche hier im Forum danach liefert kein einziges Thema wo Currying mal behandelt wird. Nur einen Artikel wo das als Möglichkeit erwähnt wird, eine Einladung zu einem Usergroup Treffen in dem es als Feature von F# vorgestellt wird, und dann meine Frage hier im Thread ;)
Wie dem auch sei - du bist dran :)
|
|
09.05.2010 23:21
|
E-Mail |
Beiträge des Benutzers |
zu Buddylist hinzufügen
|
|
dN!3L
myCSharp.de-Poweruser/ Experte
Dabei seit: 13.08.2004
Beiträge: 2.829
|
|
| Zitat von talla: |
| Durch die Antwort ist ja praktisch schon verraten das es natürlich in C# geht - ich hätte neben der Lösung aber auch noch den Namen der Technik ( aber bitte beides zusammen, nur die Nennung des Namens würde die Lösung dann durch suchen im Inet trivial machen) |
Das Vorgehen nennt sich "Currying". Funktioniert in C# folgendermaßen:
C#-Code: |
using System;
public static class Program
{
public static Func<A,Func<B,Func<C,Func<D,R>>>> SomethingNice<A,B,C,D,R>(this Func<A,B,C,D,R> f)
{
return a => b => c => d => f(a,b,c,d);
}
public static void Main(string[] args)
{
Func<int,int,int,int,int> add = (a,b,c,d) => a + b + c + d;
var erg = add(1,2,3,4);
var erg2 = add.SomethingNice()(1)(2)(3)(4);
var tmp = add.SomethingNice()(1)(3);
var erg3 = tmp(4)(2);
}
}
|
EDIT: GRML! Zu langsam...
Gruß,
dN!3L
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von dN!3L am 09.05.2010 23:27.
|
|
09.05.2010 23:26
|
Beiträge des Benutzers |
zu Buddylist hinzufügen
|
|
Corpsegrinder
myCSharp.de-Mitglied
Dabei seit: 30.01.2007
Beiträge: 401
Entwicklungsumgebung: VS 2008 , .Net 3.5
|
|
Okay, da wir hier gerade so schön bei funktionaler Programmierung sind ist meine Aufgabe auch in diesem Bereich angesiedelt.
Es soll eine Erweiterung für die Klasse List<T> geschrieben werden, welche eine Methode FoldLeft bereitstellt. FoldLeft bekommt einen Anfangswert vom Typen T und eine Funktion übergeben. Die übergebene Funktion wird für jedes Element der Liste mit dem Ergebnis des vorherigen Aufrufs und dem aktuellen Element aufgerufen. Der erste Aufruf geschieht mit dem Anfangswert und dem Element, da dort ja noch kein Ergebnis vorhanden ist ;-)
|
|
10.05.2010 10:18
|
E-Mail |
Beiträge des Benutzers |
zu Buddylist hinzufügen
|
|
herbivore
myCSharp.de-Team (Admin)
Dabei seit: 11.01.2005
Beiträge: 47.492
Entwicklungsumgebung: csc/nmake (nothing is faster) Herkunft: Berlin
|
|
Hallo Corpsegrinder,
das war ja mal eine kleine, schöne Aufgabe. Hier meine Lösung. Damit daraus eine Erweiterungsmethode wird, müsste man wohl nur ein this an den Beginn der Parameterliste von FoldLeft setzen. Hier habe ich momentan nur C# 2.0, weshalb ich das nicht testen konnte.
C#-Code: |
public delegate T FoldFunc <T> (T accumulatedValue, T currentValue);
public static T FoldLeft <T> (List <T> list, T startValue, FoldFunc <T> foldFunc)
{
T accumulatedValue = startValue;
foreach (T currentValue in list) {
accumulatedValue = foldFunc (accumulatedValue, currentValue);
}
return accumulatedValue;
}
|
herbivore
|
|
10.05.2010 10:41
|
E-Mail |
Beiträge des Benutzers |
zu Buddylist hinzufügen
|
|
herbivore
myCSharp.de-Team (Admin)
Dabei seit: 11.01.2005
Beiträge: 47.492
Entwicklungsumgebung: csc/nmake (nothing is faster) Herkunft: Berlin
|
|
Hallo zusammen,
dann kommt jetzt eine weitere Episode zum Thema, iterativ programmieren, was man üblicherweise rekursiv lösen würde.
Für die folgende Klasse Tree soll die innere Klasse Enumerator so implementiert werden, dass die Knoten des Baums von foreach (T t in root) depth-first in-order durchlaufen werden.- Dabei dürfen keine rekursiven Methoden verwendet werden.
- Entsprechend bringt die Verwendung von yield return auch keine Vorteile und sollte unterbleiben.
- Man darf sich allerdings den aktuellen Pfad (und etwaige Zusatzinformationen) in einem Stack<> merken (ganz ohne kommt man vermutlich nur aus, wenn die Tree-Klasse um eine Property Parent erweitert wird; eine solchermaßen erweiterte Klasse findet sich im folgenden Post).
- Andere Collections sollten nicht verwendet werden, also insbesondere keine List<>, in die schon im Konstruktor alle Knoten in der richtigen Reihenfolge gepackt werden.
- Der Enumerator darf ungeprüft davon ausgehen, dass der Baum während der Aufzählung nicht verändert wird.
- Der Enumerator darf ungeprüft davon ausgehen, dass der Baum wohlgeformt ist, also dass er keine Zyklen enthält und auf jeden Knoten im Baum (außer der Wurzel) nur von genau einem (Vater-)Knoten aus verwiesen wird.
|
C#-Code: |
using System;
using System.Collections.Generic;
using IUntypedEnumerable = System.Collections.IEnumerable;
using IUntypedEnumerator = System.Collections.IEnumerator;
public class Tree <T> : IEnumerable <T>
{
public Tree (T value)
{
_value = value;
}
private T _value;
private Tree <T> _left;
private Tree <T> _right;
public T Value
{
get { return _value; }
set { _value = value; }
}
public Tree <T> Left
{
get { return _left; }
set { _left = value; }
}
public Tree <T> Right
{
get { return _right; }
set { _right = value; }
}
public IEnumerator <T> GetEnumerator ()
{
return new Enumerator (this);
}
IUntypedEnumerator IUntypedEnumerable.GetEnumerator ()
{
return GetEnumerator ();
}
private class Enumerator : IEnumerator <T>
{
}
}
|
herbivore
|
|
10.05.2010 12:46
|
E-Mail |
Beiträge des Benutzers |
zu Buddylist hinzufügen
|
|
herbivore
myCSharp.de-Team (Admin)
Dabei seit: 11.01.2005
Beiträge: 47.492
Entwicklungsumgebung: csc/nmake (nothing is faster) Herkunft: Berlin
|
|
Hallo zusammen,
hier noch die Klasse Tree mit Parent-Property, für alle, die - was ich sehr begrüßen würde - ganz ohne Stack<> auskommen wollen (s. Aufgabenbeschreibung im vorigen Beitrag).
C#-Code: |
using System;
using System.Collections.Generic;
using System.Diagnostics;
using IUntypedEnumerable = System.Collections.IEnumerable;
using IUntypedEnumerator = System.Collections.IEnumerator;
public class Tree <T> : IEnumerable <T>
{
public Tree (T value)
{
_value = value;
}
private T _value;
private Tree <T> _left;
private Tree <T> _right;
private Tree <T> _parent;
public T Value
{
get { return _value; }
set { _value = value; }
}
public Tree <T> Left
{
get { return _left; }
set {
if (_left == value) {
return;
}
if (value == null) {
Debug.Assert (_left != null);
_left._parent = null;
_left = null;
return;
}
Debug.Assert (value != null);
if (value._parent != null) {
if (value._parent._left == value) {
value._parent._left = null;
} else {
Debug.Assert (value._parent._right == value);
value._parent._right = null;
}
}
_left = value;
value._parent = this;
}
}
public Tree <T> Right
{
get { return _right; }
set {
if (_right == value) {
return;
}
if (value == null) {
Debug.Assert (_right != null);
_right._parent = null;
_right = null;
return;
}
Debug.Assert (value != null);
if (value._parent != null) {
if (value._parent._left == value) {
value._parent._left = null;
} else {
Debug.Assert (value._parent._right == value);
value._parent._right = null;
}
}
_right = value;
value._parent = this;
}
}
public Tree <T> Parent
{
get { return _parent; }
}
public IEnumerator <T> GetEnumerator ()
{
return new Enumerator (this);
}
IUntypedEnumerator IUntypedEnumerable.GetEnumerator ()
{
return GetEnumerator ();
}
private class Enumerator : IEnumerator <T>
{
}
}
|
herbivore
|
|
10.05.2010 15:52
|
E-Mail |
Beiträge des Benutzers |
zu Buddylist hinzufügen
|
|
Tarion
myCSharp.de-Mitglied
Dabei seit: 23.03.2009
Beiträge: 380
Entwicklungsumgebung: VS2010 Ultimate
|
|
Ich muss zugeben, ich hab mir den Algorithmus nicht selbst ausgedacht. Er ist bekannt als Morris Traversal.
Die Implementierung stammt jedoch komplett von mir.
C#-Code: |
private class Enumerator : IEnumerator<T>
{
private Tree<T> root;
private Tree<T> current;
private bool running;
public Enumerator(Tree<T> root)
{
this.root = root;
Reset();
}
#region IEnumerator<T> Members
public T Current
{
get { return current.Value; }
}
#endregion
#region IEnumerator Members
object System.Collections.IEnumerator.Current
{
get { return this.Current; }
}
public bool MoveNext()
{
if (running)
{
current = current.Right;
}
else running = true;
while (true)
{
if (current == null)
return false;
if (current.Left == null)
{
return true;
}
else
{
Tree<T> pre;
pre = current.Left;
while (pre.Right != null && pre.Right != current)
pre = pre.Right;
if (pre.Right == null)
{
pre.Right = current;
current = current.Left;
}
else
{
pre.Right = null;
return true;
}
}
}
}
public void Reset()
{
current = root;
running = false;
}
#endregion
#region IDisposable Members
public void Dispose()
{
}
#endregion
}
|
Dieser Beitrag wurde 5 mal editiert, zum letzten Mal von Tarion am 10.05.2010 17:42.
|
|
10.05.2010 17:05
|
E-Mail |
Beiträge des Benutzers |
zu Buddylist hinzufügen
|
 |
Moderationshinweis von herbivore (26.07.2012 08:53):
Das ist noch nicht die abschließende Lösung der Aufgabe, weiter geht es auf der nächsten Seite.
|
|
|
|