myCSharp.de - DIE C# und .NET Community
Willkommen auf myCSharp.de! Anmelden | kostenlos registrieren
 | Suche | FAQ

» Hauptmenü
myCSharp.de
» Startseite
» Forum
» FAQ
» Artikel
» C#-Snippets
» Jobbörse
» Suche
   » Plugin für Firefox
   » Plugin für IE7
   » Gadget für Vista
» Regeln
» Wie poste ich richtig?
» Datenschutzerklärung
» wbb-FAQ

Mitglieder
» Liste / Suche
» Stadt / Anleitung dazu
» Wer ist wo online?

Angebote
» ASP.NET Webspace
» Bücher
» Zeitschriften
   » dot.net magazin
» Accessoires

Ressourcen
» .NET-Glossar
» guide to C#
» openbook: Visual C#
» openbook: OO
» .NET BlogBook
» MSDN Webcasts
» dotnetjob.de
» Search.Net

Team
» Kontakt
» Übersicht
» Wir über uns
» Bankverbindung
» Impressum

» Unsere MiniCity
MiniCity
» myCSharp.de Diskussionsforum
Du befindest Dich hier: Community-Index » Diskussionsforum » Gemeinschaft » Smalltalk » Das Programmier-Spiel: nette Übungsaufgaben für zwischendurch
Letzter Beitrag | Erster ungelesener Beitrag Druckvorschau | An Freund senden | Thema zu Favoriten hinzufügen

Seiten (17): « vorherige 1 2 3 [4] 5 6 7 8 nächste » ... letzte » Antwort erstellen
Zum Ende der Seite springen  

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

 
Autor
Beitrag « Vorheriges Thema | Nächstes Thema »
dN!3L dN!3L ist männlich
myCSharp.de-Poweruser/ Experte

images/avatars/avatar-2985.png


Dabei seit: 13.08.2004
Beiträge: 2.829


dN!3L ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top



Zitat von edsplash:
stellt quasi eine 1:1 Verknüpfung, bzw. eine eindeutige Zuordnung

*klugscheiß* Du meinst eineindeutig!? Als bijektiv (rechtseindeutig/surjektiv und linkseindeutig/injektiv).
04.05.2010 14:16 Beiträge des Benutzers | zu Buddylist hinzufügen
inflames2k inflames2k ist männlich
myCSharp.de-Mitglied

images/avatars/avatar-3407.gif


Dabei seit: 03.01.2010
Beiträge: 1.526
Entwicklungsumgebung: Visual Studio 2005 Standard
Herkunft: Riesa


inflames2k ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

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)

images/avatars/avatar-2627.gif


Dabei seit: 11.01.2005
Beiträge: 47.498
Entwicklungsumgebung: csc/nmake (nothing is faster)
Herkunft: Berlin


herbivore ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

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
inflames2k inflames2k ist männlich
myCSharp.de-Mitglied

images/avatars/avatar-3407.gif


Dabei seit: 03.01.2010
Beiträge: 1.526
Entwicklungsumgebung: Visual Studio 2005 Standard
Herkunft: Riesa


inflames2k ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Stimmt, gab ja noch die Zuordnung per Objekt[key]. - Hab es im Code angepasst.
04.05.2010 15:04 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
herbivore
myCSharp.de-Team (Admin)

images/avatars/avatar-2627.gif


Dabei seit: 11.01.2005
Beiträge: 47.498
Entwicklungsumgebung: csc/nmake (nothing is faster)
Herkunft: Berlin


herbivore ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

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 inflames2k ist männlich
myCSharp.de-Mitglied

images/avatars/avatar-3407.gif


Dabei seit: 03.01.2010
Beiträge: 1.526
Entwicklungsumgebung: Visual Studio 2005 Standard
Herkunft: Riesa


inflames2k ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

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 edsplash ist männlich
myCSharp.de-Mitglied

images/avatars/avatar-3111.jpg


Dabei seit: 19.04.2008
Beiträge: 390
Entwicklungsumgebung: VS2010


edsplash ist offline Füge edsplash Deiner Kontaktliste hinzu

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

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 TheBrainiac ist männlich
myCSharp.de-Mitglied

images/avatars/avatar-3152.png


Dabei seit: 17.12.2006
Beiträge: 767
Entwicklungsumgebung: VS 2010 Prof.
Herkunft: /dev/null


TheBrainiac ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

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];
    }

    /// <summary>
    /// Fügt der Map eine Zuordnung hinzu
    /// </summary>
    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++;
    }

    /// <summary>
    /// Liest ein Element auf der rechten Seite der Map aus oder setzt dieses
    /// </summary>
    /// <param name="item">Ein Element auf der linken Seite, welches als Schlüssel dient</param>
    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;
            }
        }
    }

    /// <summary>
    /// Liest ein Element auf der linken Seite der Map aus oder setzt dieses
    /// </summary>
    /// <param name="item">Ein Element auf der rechten Seite, welches als Schlüssel dient</param>
    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;
            }
        }
    }

    /// <summary>
    /// Gibt an, ob auf der linken Seite ein spezifisches Element vorhanden ist
    /// </summary>
    public Boolean Contains(TLeft item) {
        return Find(item) != -1;
    }

    /// <summary>
    /// Gibt an, ob auf der rechten Seite ein spezifisches Element vorhanden ist
    /// </summary>
    public Boolean Contains(TRight item) {
        return Find(item) != -1;
    }

    /// <summary>
    /// Löscht eine Zuordnung
    /// </summary>
    /// <param name="item">Ein Element auf der linken Seite, welches als Schlüssel dient</param>
    public Boolean Remove(TLeft item) {
        return Remove(Find(item));
    }

    /// <summary>
    /// Löscht eine Zuordnung
    /// </summary>
    /// <param name="item">Ein Element auf der rechten Seite, welches als Schlüssel dient</param>
    public Boolean Remove(TRight item) {
        return Remove(Find(item));
    }

    /// <summary>
    /// Löscht alle Zuordnungen
    /// </summary>
    public void Clear() {
        m_Used = new Boolean[m_Used.Length];
        m_Left = new TLeft[m_Left.Length];
        m_Right = new TRight[m_Right.Length];
    }

    /// <summary>
    /// Gibt die Anzahl der vorhandenen Zuordnungen zurück
    /// </summary>
    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 inflames2k ist männlich
myCSharp.de-Mitglied

images/avatars/avatar-3407.gif


Dabei seit: 03.01.2010
Beiträge: 1.526
Entwicklungsumgebung: Visual Studio 2005 Standard
Herkunft: Riesa


inflames2k ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

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 TheBrainiac ist männlich
myCSharp.de-Mitglied

images/avatars/avatar-3152.png


Dabei seit: 17.12.2006
Beiträge: 767
Entwicklungsumgebung: VS 2010 Prof.
Herkunft: /dev/null


TheBrainiac ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

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
Th69
myCSharp.de-Poweruser/ Experte

images/avatars/avatar-2578.jpg


Dabei seit: 01.04.2008
Beiträge: 1.802
Entwicklungsumgebung: Visual Studio 2005/08/10


Th69 ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Na, dann darf ich ja wohl nicht mitmachen großes Grinsen
05.05.2010 10:09 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
TheBrainiac TheBrainiac ist männlich
myCSharp.de-Mitglied

images/avatars/avatar-3152.png


Dabei seit: 17.12.2006
Beiträge: 767
Entwicklungsumgebung: VS 2010 Prof.
Herkunft: /dev/null


TheBrainiac ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

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 MarsStein ist männlich
myCSharp.de-Team (Moderation)

images/avatars/avatar-3191.gif


Dabei seit: 27.06.2006
Beiträge: 2.718
Entwicklungsumgebung: VS 2010, MonoDevelop, #Develop
Herkunft: Trier -> München


MarsStein ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

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)
    {
// die folgende Zeile wiede4r einkommentieren um das Verfahren zu sehen
//    Console.WriteLine(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]))) // <<< hier das IsDigit eingebaut
            {
              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 JAck30lena ist männlich
myCSharp.de-Team (Admin)

images/avatars/avatar-2653.jpg


Dabei seit: 01.10.2006
Beiträge: 11.393
Entwicklungsumgebung: Visual Studio 05/08/10 Prof.


JAck30lena ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

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 MarsStein ist männlich
myCSharp.de-Team (Moderation)

images/avatars/avatar-3191.gif


Dabei seit: 27.06.2006
Beiträge: 2.718
Entwicklungsumgebung: VS 2010, MonoDevelop, #Develop
Herkunft: Trier -> München


MarsStein ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

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 JAck30lena ist männlich
myCSharp.de-Team (Admin)

images/avatars/avatar-2653.jpg


Dabei seit: 01.10.2006
Beiträge: 11.393
Entwicklungsumgebung: Visual Studio 05/08/10 Prof.


JAck30lena ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

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 MarsStein ist männlich
myCSharp.de-Team (Moderation)

images/avatars/avatar-3191.gif


Dabei seit: 27.06.2006
Beiträge: 2.718
Entwicklungsumgebung: VS 2010, MonoDevelop, #Develop
Herkunft: Trier -> München


MarsStein ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

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)
    {
      // die folgende Zeile wiede4r einkommentieren um das Verfahren zu sehen
      //    Console.WriteLine(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));
            // partRes = double.NaN;  <<< die böse Zeile (siehe Folgebeiträge)
            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]))) // <<< hier das IsDigit eingebaut
          {
            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
JAck30lena JAck30lena ist männlich
myCSharp.de-Team (Admin)

images/avatars/avatar-2653.jpg


Dabei seit: 01.10.2006
Beiträge: 11.393
Entwicklungsumgebung: Visual Studio 05/08/10 Prof.


JAck30lena ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

ich kann keine fehler mehr feststellen. wunderschöne lösung. respekt :-)
06.05.2010 10:25 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
TheBrainiac TheBrainiac ist männlich
myCSharp.de-Mitglied

images/avatars/avatar-3152.png


Dabei seit: 17.12.2006
Beiträge: 767
Entwicklungsumgebung: VS 2010 Prof.
Herkunft: /dev/null


TheBrainiac ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

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

images/avatars/avatar-3070.jpg


Dabei seit: 25.10.2009
Beiträge: 453


Cat ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

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 MarsStein ist männlich
myCSharp.de-Team (Moderation)

images/avatars/avatar-3191.gif


Dabei seit: 27.06.2006
Beiträge: 2.718
Entwicklungsumgebung: VS 2010, MonoDevelop, #Develop
Herkunft: Trier -> München


MarsStein ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

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 TheBrainiac ist männlich
myCSharp.de-Mitglied

images/avatars/avatar-3152.png


Dabei seit: 17.12.2006
Beiträge: 767
Entwicklungsumgebung: VS 2010 Prof.
Herkunft: /dev/null


TheBrainiac ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

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 MarsStein ist männlich
myCSharp.de-Team (Moderation)

images/avatars/avatar-3191.gif


Dabei seit: 27.06.2006
Beiträge: 2.718
Entwicklungsumgebung: VS 2010, MonoDevelop, #Develop
Herkunft: Trier -> München


MarsStein ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hallo,

Zitat von JAck30lena:
wunderschöne lösung. respekt :-)

danke dafür und für den Hinweis wegen NaN smile
Rekursion mal von hinten nach vorn und von innen nach außen großes Grinsen großes Grinsen

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 talla ist männlich
myCSharp.de-Team (Moderation)

images/avatars/avatar-3214.jpg


Dabei seit: 20.07.2003
Beiträge: 6.863
Entwicklungsumgebung: VS 2010
Herkunft: Esslingen


talla ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

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) {

            // Skalierungsfaktor anhand der größten Kugelmenge berechnen
            var scale = 75.0 / bins.Max();

            for (int i = 0; i < bins.Length - 1; i++) {
                // Anzahl zu druckender Zeichen bestimmen
                var end = (int)(bins[i] * scale);

                for (int j = 0; j < end; j++) {
                    Console.SetCursorPosition(j, startY + i*2);
                    Console.Write("x");
                }

                // Noch die Anzahl der Kugeln an den Anfang schreiben
                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;

            // Fakultät
            factorial = (n) => (n == 0) ? 1 : n * factorial(n - 1);
            // Binomialkoeffizenten
            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)));
            }

            // Summen für jedes Fach aufaddieren, siehe DropBalls für warum
            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) {
            // Fächer
            int[] bins = new int[factors.Count];

            // für jeden gezogenen Ball...
            for (int i = 0; i < balls; i++) {
                // Zufallszahl erzeugen
                var num = rand.NextDouble()*sum;
                // Fächersummen durchgehen wenn Zufallszahl kleiner als Summe, ist die Kugel ins vorherige Fach gefallen
                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 MarsStein ist männlich
myCSharp.de-Team (Moderation)

images/avatars/avatar-3191.gif


Dabei seit: 27.06.2006
Beiträge: 2.718
Entwicklungsumgebung: VS 2010, MonoDevelop, #Develop
Herkunft: Trier -> München


MarsStein ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hallo talla,

da die Skalierung ausdrücklich gefordert war, kann ich Deine Lösung leider so nicht durchgehen lassen unglücklich
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 talla ist männlich
myCSharp.de-Team (Moderation)

images/avatars/avatar-3214.jpg


Dabei seit: 20.07.2003
Beiträge: 6.863
Entwicklungsumgebung: VS 2010
Herkunft: Esslingen


talla ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

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;
            // skalieren mit dem 10er Logarithmus des Maximums
            var log = (int)Math.Log10(max);
            for (int i = 0; i < log; i++) {
                baseChars += 5.0;
            }

            // Skalierungsfaktor anhand der größten Kugelmenge berechnen
            var scale = baseChars / bins.Max();
            var offset = 10;

            for (int i = 0; i < bins.Length - 1; i++) {
                // Anzahl zu druckender Zeichen bestimmen
                var end = (int)(bins[i] * scale);

                for (int j = 0; j < end; j++) {
                    Console.SetCursorPosition(offset + j, startY + i*2);
                    Console.Write("x");
                }

                // Noch die Anzahl der Kugeln an den Anfang schreiben
                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 MarsStein ist männlich
myCSharp.de-Team (Moderation)

images/avatars/avatar-3191.gif


Dabei seit: 27.06.2006
Beiträge: 2.718
Entwicklungsumgebung: VS 2010, MonoDevelop, #Develop
Herkunft: Trier -> München


MarsStein ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

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 smile

Gruß, MarsStein
09.05.2010 12:40 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
talla talla ist männlich
myCSharp.de-Team (Moderation)

images/avatars/avatar-3214.jpg


Dabei seit: 20.07.2003
Beiträge: 6.863
Entwicklungsumgebung: VS 2010
Herkunft: Esslingen


talla ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

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


Corpsegrinder ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

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 talla ist männlich
myCSharp.de-Team (Moderation)

images/avatars/avatar-3214.jpg


Dabei seit: 20.07.2003
Beiträge: 6.863
Entwicklungsumgebung: VS 2010
Herkunft: Esslingen


talla ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

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


Corpsegrinder ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

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 talla ist männlich
myCSharp.de-Team (Moderation)

images/avatars/avatar-3214.jpg


Dabei seit: 20.07.2003
Beiträge: 6.863
Entwicklungsumgebung: VS 2010
Herkunft: Esslingen


talla ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

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 dN!3L ist männlich
myCSharp.de-Poweruser/ Experte

images/avatars/avatar-2985.png


Dabei seit: 13.08.2004
Beiträge: 2.829


dN!3L ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

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


Corpsegrinder ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

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)

images/avatars/avatar-2627.gif


Dabei seit: 11.01.2005
Beiträge: 47.498
Entwicklungsumgebung: csc/nmake (nothing is faster)
Herkunft: Berlin


herbivore ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

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
dN!3L dN!3L ist männlich
myCSharp.de-Poweruser/ Experte

images/avatars/avatar-2985.png


Dabei seit: 13.08.2004
Beiträge: 2.829


dN!3L ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top



Zitat von Corpsegrinder:
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 ;-)

Gibt's doch schon im Framework!?
 IEnumerable.Aggregate-Methode


mycsharp.de  Moderationshinweis von herbivore (10.05.2010 11:15):

Lösungen zu den meisten der Aufgaben, die hier gestellt werden, gibt es schon irgendwie und irgendwo. Das ist kein KO-Kriterium für das Programmierspiel. Jeder Mitspieler ist aber mehr als gehalten eine eigene Lösung zu erstellen und nicht einfach eine fremde zu posten.

Als reine Information lass ich deinen Beitrag mal stehen.

 
10.05.2010 10:59 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


Corpsegrinder ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Alles klar herbivore, funktioniert super. Dann stell mal die nächste Aufgabe ;-)
10.05.2010 11:47 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
herbivore
myCSharp.de-Team (Admin)

images/avatars/avatar-2627.gif


Dabei seit: 11.01.2005
Beiträge: 47.498
Entwicklungsumgebung: csc/nmake (nothing is faster)
Herkunft: Berlin


herbivore ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

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)

images/avatars/avatar-2627.gif


Dabei seit: 11.01.2005
Beiträge: 47.498
Entwicklungsumgebung: csc/nmake (nothing is faster)
Herkunft: Berlin


herbivore ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

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 Tarion ist männlich
myCSharp.de-Mitglied

images/avatars/avatar-91.gif


Dabei seit: 23.03.2009
Beiträge: 380
Entwicklungsumgebung: VS2010 Ultimate


Tarion ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

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; }
            }

            /// <summary>
            /// Morris Traversal
            /// </summary>
            /// <returns></returns>
            public bool MoveNext()
            {
                // skip this the first time
                if (running)
                {
                    current = current.Right;
                }
                else running = true;

                while (true)
                {
                    // if current is null, we are done.
                    if (current == null)
                        return false;

                    if (current.Left == null)
                    {
                        // Print Current if left is empty
                        return true;
                    }
                    else
                    {
                        // Find the inorder predecessor of current
                        Tree<T> pre;
                        pre = current.Left;
                        while (pre.Right != null && pre.Right != current)
                            pre = pre.Right;

                        // Make current as right child of its inorder predecessor
                        if (pre.Right == null)
                        {
                            pre.Right = current;
                            current = current.Left;
                        }
                        else
                        {
                            // Revert the changes to restore the original tree: fix the right child of predecssor
                            pre.Right = null;

                            // Print Current
                            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
myCSharp.de
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.
 
Seiten (17): « vorherige 1 2 3 [4] 5 6 7 8 nächste » ... letzte » Baumstruktur | Brettstruktur       | Top 
myCSharp.de | Forum Der Startbeitrag ist älter als 3 Jahre.
Der letzte Beitrag ist älter als 2 Monate.
Antwort erstellen


© Copyright 2003-2013 myCSharp.de-Team. Alle Rechte vorbehalten. 26.05.2013 08:57