HiveBrain v1.2.0
Get Started
← Back to all entries
patterncsharpMinor

Rewriting C# implementation of Snake class in F#

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
implementationclasssnakerewriting

Problem

This is my C# class, which takes 2.6s:

class Snake
{
    readonly Symbol _mySymbol;
    readonly int _multiplier;
    readonly int _hit;
    readonly int _payout;
    readonly Snake _bestSnake;

    public Symbol MySymbol { get { return _mySymbol; } }
    public int Multiplier { get { return _multiplier; } }
    public int Hit { get { return _hit; } }
    public int Payout { get { return _payout; } }

    public Snake BestSnake { get { return _bestSnake; } }

    public Snake(Apple myApple)
    {
        this._mySymbol = myApple.MySymbol;
        this._multiplier = myApple.Multiplier;
        this._hit = 1;
        this._payout = _mySymbol.Payout_[0] * (_multiplier == 0 ? 1 : _multiplier);
        this._bestSnake = this;
    }

    Snake(Symbol mySymbol, int multiplier, int hit)
    {
        this._mySymbol = mySymbol;
        this._multiplier = multiplier;
        this._hit = hit;
        this._payout = _mySymbol.Payout_[hit - 1] * (multiplier == 0 ? 1 : multiplier);
        this._bestSnake = this;
    }

    Snake(Symbol mySymbol, int multiplier, int hit, Snake bestRecentSnake)
        : this(mySymbol, multiplier, hit)
    {
        if (_payout < bestRecentSnake._payout)
        {
            this._bestSnake = bestRecentSnake;
        }
        else if (_payout == bestRecentSnake._payout)
        {
            if (bestRecentSnake._mySymbol.Type == 1 && mySymbol.Type != 1)
            {
                this._bestSnake = bestRecentSnake;
            }
        }
    }

    public Snake Eat(Apple nextApple)
    {
        var resultSymbol = Symbol.Add(_mySymbol, nextApple.MySymbol);
        if (resultSymbol == null)
            return null;

        var newSnake = new Snake(resultSymbol, Math.Max(_multiplier, nextApple.Multiplier), Hit + 1, _bestSnake);

        return newSnake;
    }


This is my F# class, which takes 5s:

```
type Snake (mySymbol: Symbol, multiplier, hit, best: Option) =

let payout (mySymbol: Symbol) hit multiplier =
match multiplier wi

Solution

There are a few small differences in your translation. I would start with as literal a translation possible, then optimize/make idiomatic from there. If done incrementally it should be easy to spot performance problems as they occur. Here's a starting point:

( stub )
[]
type Symbol =
member x.Payout = [|0|]
member x.Type = 0
static member Add(sym1, sym2) : Symbol = null

( stub )
type Apple =
abstract MySymbol : Symbol
abstract Multiplier : int

type private BestSnake =
| This
| RecentSnake of Snake

and [] Snake private (mySymbol: Symbol, multiplier, hit, bestSnake) as this =
let payout = mySymbol.Payout.[hit - 1] * (match multiplier with 0 -> 1 | m -> m)
let bestSnake =
match bestSnake with
| This -> this
| RecentSnake bestRecentSnake ->
if payout 1)
then bestRecentSnake
else null

member val MySymbol : Symbol = mySymbol
member val Multiplier = multiplier
member val Hit = hit
member val BestSnake = bestSnake
member val Payout = payout

new (mySymbol, multiplier, hit, bestRecentSnake) = Snake(mySymbol, multiplier, hit, RecentSnake bestRecentSnake)
new (mySymbol, multiplier, hit) = Snake(mySymbol, multiplier, hit, This)
new (myApple: Apple) = Snake(myApple.MySymbol, myApple.Multiplier, 1, This)

member this.Eat(nextApple: Apple) =
match Symbol.Add(this.MySymbol, nextApple.MySymbol) with
| null -> null
| resultSymbol -> Snake(resultSymbol, max this.Multiplier nextApple.Multiplier, this.Hit + 1, this.BestSnake)


The performance of this should be on par with C#.

Context

StackExchange Code Review Q#15542, answer score: 5

Revisions (0)

No revisions yet.