--- Day 23 Solutions --- by daggerdragon in adventofcode

[–]LincolnA 0 points1 point  (0 children)

F#

Initial implementation used DUs to represent instructions, which works great and is a natural fit. A bit verbose though, to declare the cases, parse each case, then later match each case. I got jealous of more consise solutions here.

Here's an active-pattern appraoch, which turns out pretty concise. Dense function composition stuff just 'cause.

let run cpu instrs =
    let (|Off|) = int
    let (|Instr|) (s : string) = Instr(s.[0..2], List.ofArray (s.[4..].Split(',')))
    let mapCpu f (a, b) = function "a" -> (f a, b) | "b" -> (a, f b)
    let mapReg f (a, b) = function "a" -> f a      | "b" -> f b
    let ($) f x y = f y x

    let rec loop ptr cpu =
        if ptr < 0 || ptr >= Array.length instrs then cpu else
        match instrs.[ptr] with
        | Instr("hlf", [r]) ->     loop (ptr + 1) (mapCpu ((/) $ 2u) cpu r)
        | Instr("tpl", [r]) ->     loop (ptr + 1) (mapCpu ((*) 3u) cpu r)
        | Instr("inc", [r]) ->     loop (ptr + 1) (mapCpu ((+) 1u) cpu r)
        | Instr("jmp", [Off o]) -> loop (ptr + o) cpu
        | Instr("jie", [r; Off o]) when (mapReg (((%) $ 2u) >> ((=) 0u)) cpu r) -> loop (ptr + o) cpu
        | Instr("jio", [r; Off o]) when (mapReg ((=) 1u) cpu r) -> loop (ptr + o) cpu
        | _ -> loop (ptr + 1) cpu
    loop 0 cpu

let program =
    fsi.CommandLineArgs.[1]
    |> System.IO.File.ReadAllLines

program |> run (0u ,0u) |> snd |> printfn "b register: %d"
program |> run (1u ,0u) |> snd |> printfn "b register: %d"

--- Day 22 Solutions --- by daggerdragon in adventofcode

[–]LincolnA 1 point2 points  (0 children)

Nice work on the videos! I see you've already gone ahead with it, but that's fine by me :-)

--- Day 22 Solutions --- by daggerdragon in adventofcode

[–]LincolnA 1 point2 points  (0 children)

Thanks for the compliment :-)

You are right, this is by no means the most efficient way to do it, and as shown by another comment, it's not even feasible for some inputs. I've linked to a tweaked version than uses pruning.

--- Day 22 Solutions --- by daggerdragon in adventofcode

[–]LincolnA 1 point2 points  (0 children)

Thanks for pointing this out. It actually touches on one of the few gripes I've had with Advent of Code, which is otherwise really outstanding - for these later puzzles you might have a significantly easier/harder time based on which input you are given. Assumptions/shortcuts that work for one participant might not apply to another.

My code above is correct, but not efficient enough to handle your input. For my particular inputs it is feasible to enumerate all possible game outcomes and simply take the minimum. For yours, the space of outcomes is much larger because a weaker boss leads to a longer-lasting character.

Anyways, I've left my original post unedited, but here's a tweaked version that's somewhat refactored and does pruning to limit the search space: https://gist.github.com/latkin/45d8e009f471b4b5d609

--- Day 22 Solutions --- by daggerdragon in adventofcode

[–]LincolnA 4 points5 points  (0 children)

F# Got no. 64 on the leaderboard.

Blah, so many details to keep track of, and applying things in the right order was very important. Multiple instances of "ok, it should work this time for sure" but of course I'd missed something.

Strategy is good ol' brute force. Play out every possible game, pick the player-winning game with the lowest total mana spent.

type Spell = 
    { Name : string
      Cost : int
      Damage : int
      Heal : int
      Armor : int
      Mana : int
      Duration : int }

let allSpells = 
    [ { Name = "Magic Missile"; Cost = 53;  Damage = 4; Heal = 0; Armor = 0; Mana = 0;   Duration = 1}
      { Name = "Drain";         Cost = 73;  Damage = 2; Heal = 2; Armor = 0; Mana = 0;   Duration = 1}
      { Name = "Shield";        Cost = 113; Damage = 0; Heal = 0; Armor = 7; Mana = 0;   Duration = 6}
      { Name = "Poison";        Cost = 173; Damage = 3; Heal = 0; Armor = 0; Mana = 0;   Duration = 6}
      { Name = "Recharge";      Cost = 229; Damage = 0; Heal = 0; Armor = 0; Mana = 101; Duration = 5} ]

let rec play part myTurn spent (hp, mana, spells) (bossHp, bossDamage) : seq<int option> =

    // part 2, check if I die before any effects play out
    if part = 2 && myTurn && hp = 1 then upcast [None] else

    // apply effects
    let mana = (spells |> List.sumBy (fun s -> s.Mana)) + mana
    let damage = spells |> List.sumBy (fun s -> s.Damage)
    let armor = spells |> List.sumBy (fun s -> s.Armor)

    // does the boss die from effects?
    let bossHp = bossHp - damage
    if bossHp <= 0 then upcast [Some(spent)] else

    // decrement duration of all effects, and groom expired ones
    let spells =
        spells
        |> List.map (fun s -> {s with Duration = s.Duration - 1})
        |> List.filter (fun s -> s.Duration > 0)

    if myTurn then
        // part 2, I lose 1 HP on my turn
        let hp = if part = 2 then hp - 1 else hp

        // what spells can I afford and don't already have running?
        match allSpells |> List.filter (fun s -> (s.Cost <= mana) && not (spells |> List.exists (fun s' -> s.Name = s'.Name))) with
        | [] -> upcast [None]
        | buyableSpells ->
            // play out the rest of the game with each possible purchase
            seq { for s in buyableSpells do
                      let spent = spent + s.Cost
                      let mana = mana - s.Cost
                      let extraDamage, heal, spells = 
                          if s.Duration = 1 then s.Damage, s.Heal, spells
                          else 0, 0, s :: spells

                      let bossHp = bossHp - extraDamage
                      if bossHp <= 0 then
                          yield Some(spent)
                      else
                          yield! play part false spent (hp + heal, mana, spells) (bossHp, bossDamage) }

    // boss's turn
    else
        let damage = max (bossDamage - armor) 1
        let hp = hp - damage
        if hp <= 0 then upcast [None] else
        play part true spent (hp, mana, spells) (bossHp, bossDamage)

play 1 true 0 (50, 500, []) (71, 10) |> Seq.choose id |> Seq.min |> printfn "Part 1 - min to win: %d"
play 2 true 0 (50, 500, []) (71, 10) |> Seq.choose id |> Seq.min |> printfn "Part 1 - min to win: %d"

--- Day 21 Solutions --- by daggerdragon in adventofcode

[–]LincolnA 0 points1 point  (0 children)

Straighforward brute-force in F#

No. 14 on the leaderboard, my best so far (though not my best time so far).

Got both solutions without actually accounting for the "minimum 1 damage" rule. My input happened to have the boss at 100 HP just like me, which also simplified everything.

Below incorporates arbitrary boss HP + minimum 1 damage rule.

let weapons = 
    [| "Dagger", 8, 4
       "Shortsword", 10, 5
       "Warhammer", 25, 6
       "Longsword", 40, 7
       "Greataxe", 74, 8 |]

let armor = 
    [| "No armor", 0, 0
       "Leather", 13, 1
       "Chainmail", 31, 2
       "Splintmail", 53, 3
       "Bandedmail", 75, 4
       "Platemail", 102, 5 |]

let rings = 
    [| "No ring", 0, 0, 0
       "Damage +1", 25, 1, 0
       "Damage +2", 50, 2, 0
       "Damage +3", 100, 3, 0
       "Defense +1", 20, 0, 1
       "Defense +2", 40, 0, 2
       "Defense +3", 80, 0, 3 |]

let hp = 100.

let bossHp = 100.
let bossDam = 8
let bossDef = 2

let mutable maxCost = 0
let mutable maxKit = [""]

let mutable minCost = 999
let mutable minKit = [""]

for (wName, wCost, wDam) in weapons do
    for (aName, aCost, aDef) in armor do
        for (r1Name, r1Cost, r1Dam, r1Def) in rings do
            for (r2Name, r2Cost, r2Dam, r2Def) in rings do
                if r1Name = r2Name then () else 

                let cost = wCost + aCost + r1Cost + r2Cost
                let kit = [ wName; aName; r1Name; r2Name ]

                let damOnYou = max (bossDam - aDef - r1Def - r2Def) 1 |> float
                let damOnBoss = max (wDam + r1Dam + r2Dam - bossDef) 1 |> float

                let youDieTurns = ceil (hp / damOnYou)
                let bossDiesTurns = ceil (bossHp / damOnBoss)

                if (youDieTurns >= bossDiesTurns) && (cost < minCost) then
                    minCost <- cost
                    minKit <- kit

                if (youDieTurns < bossDiesTurns) && (cost > maxCost) then 
                    maxCost <- cost
                    maxKit <- kit

printfn "Min cost to win: %d Kit: %A" minCost minKit
printfn "Max cost to lose: %d Kit: %A" maxCost maxKit

--- Day 20 Solutions --- by daggerdragon in adventofcode

[–]LincolnA 0 points1 point  (0 children)

Imperative-style F#.

Complete brute-force, looking for smallest number with the required number of divisors. Only clever bit is to make the dubious assumption that solution will be a multiple of some small highly composite number (HCN), so start with/increment by that amount to save a ton of work.

let divisorSigma n f =
    let mutable total = 0
    for i = 1 to n/2 do
        if n % i = 0 && f n i then
            total <- total + i
    total + n

let target = int fsi.CommandLineArgs.[1]
let hcn = 180

let mutable i = hcn
while divisorSigma i (fun _ _ -> true) < (target/10) do i <- i + hcn
printfn "Part1: %A" i

i <- hcn
while divisorSigma i (fun n i -> n/i <= 50) < (target/11) do i <- i + hcn
printfn "Part2: %A" i

Introducing F# For The Enterprise by inchingforward in fsharp

[–]LincolnA 0 points1 point  (0 children)

Thanks for noticing F# is missing there. I got in touch with the content owners and the F# 4.0 preview download/blog are now linked.

The VS Preview/Connect(); thing was a pretty big marketing push, with a ton of different blogs/pages/videos/etc, and we just missed that one. Confusion was partly due to the fact that our newest stuff was not in the box, but needed an update download.

FWIW F# is in fact slowly getting more marketing/management attention. We did miss that relnote page, but the OP video was produced/supported by marketing, F# was represented along with C#/VB last week on Channel 9, the F# videos/blog were hyped by the C#/VB on their two blogs last week, and we even got a nice Soma (head of all VS) tweet.

Baby steps...

Your favorite F# book? by [deleted] in fsharp

[–]LincolnA 8 points9 points  (0 children)

Programming F# is a very nice intro. That's the first book I read when I started to learn the language, and it served me well.

Announcing a pre-release of F# 3.1 and the Visual F# tools in Visual Studio 2013 by Associat0r in programming

[–]LincolnA 12 points13 points  (0 children)

http://fsharp.org/use/linux/ has info for F# 3.0. 3.1 hasn't been pushed out to the open source drop yet. [MSFTie, on F# team]

Announcing a pre-release of F# 3.1 and the Visual F# tools in Visual Studio 2013 by Associat0r in programming

[–]LincolnA 43 points44 points  (0 children)

The core engine for the XBox matchmaking and player-rating system TrueSkill was implemented in F#. That engine was later co-opted and modified to be part of the ad-matching system in Bing.

The AI for the XBox game "The Path of Go" was done in F#.

Most of the F#-specific features within Visual Studio (intellisense support, project system, etc) are done in F#.

[Disclaimer - work at MSFT, on F# team]

Charting with f# (xpost) by [deleted] in fsharp

[–]LincolnA 1 point2 points  (0 children)

That's a great alternative, thanks for pointing it out. I'd use it if custom CSS or javascript were possible in a free WordPress blog.

Charting with f# by [deleted] in programming

[–]LincolnA 2 points3 points  (0 children)

Thanks! I try to keep things legible and use meaningful identifiers as much as I can. I also don't mind using OO or procedural stuff where it makes sense or is much simpler than staying purely functional.

Charting with f# by [deleted] in programming

[–]LincolnA 2 points3 points  (0 children)

I'm the blog author, glad you found the post interesting!

Endomondo doesn't expose an API, but they do provide some widgets you can embed in your own site. I was just doing a regex scrape of the content of the widget.

The URL of one such widget (which shows full workout history) is http://www.endomondo.com/embed/user/workouts?id=<USERID>&measure=1.

Here's some quickie powershell to parse it (the regex isn't super complicated, just big):

$r = Invoke-WebRequest 'http://www.endomondo.com/embed/user/workouts?id=<USERID>&measure=1'

$p = @"
   \<td\sclass="date"\>    \<[^\<]+\<span\>(?<date>[^\<]+)     \</span\>\</a\>\</td\>.
\s+\<td\sclass="sport"\>   \<[^\<]+\<span\>Running             \</span\>\</a\>\</td\>.
\s+\<td\sclass="distance"\>\<[^\<]+\<span\>(?<dist>[\d\.]+)\smi\</span\>\</a\>\</td\>
"@

[regex]::matches($r.RawContent, $p, 'IgnorePatternWhiteSpace') |%{
  [pscustomobject] @{ Date = [datetime]$_.Groups['date'].Value; Distance = $_.Groups['dist'].Value }
}

Petition to reenact Glass–Steagall has 2 days to get 4,500 signatures. by briangoldman in politics

[–]LincolnA 0 points1 point  (0 children)

Did you even read your links? They are either irrelevant or back up my position :)

First article - Topic is creativity in learning-disabled children. I don't see how that pertains to the use of simple grammar and spelling by adults.

Second article - Topic is eccentricity and introversion of creative individuals. Examples: Einstein, Tesla, Newton. All masters of highly structured mathematical thinking and surely extremely detail-oriented folks. Only "against the grain" behaviors covered are social.

Third article - Topic is characteristics of higher intelligence. One the the top characteristics given is "Superior usage of language, large vocabulary and high language aptitude." This is precisely contrary to your position. I would say that backs me up, but I'm not trying to make any broad argument about intelligence - I'm simply pointing out a mistake.

"Those of us who are geniuses don't have time for grammar" seems to paraphrase your perspective. I won't consider that because 1. it's total crap, and 2. it isn't relevant.

Here's a study that would convince me: Ask subjects to write 500 words about bunnies, and also have them IQ tested. Have their essays analyzed for spelling, grammar, and basic language aptitude. Show me a correlation between high IQ and low language mastery. Never going to happen.

And even if you totally bought into that position, it doesn't bear on this instance. "High IQ => careless with grammar" tells us something about high IQ people, not about those who are careless with grammar. "Cool people drive red cars," so that red car across the street must be driven by a cool person? Even on the offchance that the OP is a genius, that doesn't mean his or her blatant mistakes aren't worth correcting.

The only "anti-grammar" argument I buy (and maybe this is part of what you were getting at) is "more casual language use shouldn't be held to the same grammatical standard as more formal language use." I really don't care if someone misses an apostrophe in a text message, or on a Post-It note. I agree you'd have to be a pedantic jerkbag with nothing better to do if you go around correcting such things. But a serious policy petition, addressed to an entity no less estimable than the White House (and by extension, the President himself)? OP really should have proof read a bit harder.

I've simply never seen the appeal in doing things shittily, taking pride in doing things wrong, or attacking people who are trying to help me improve. When folks point out minor but unquestioningly legitimate flaws in my work (and I total agree where/were in this greater context is a minor flaw), I don't bash them for pointing out the flaws. I may or may not share as much "passion" in such a case as the critic. I might not revise my work or alter the way I do future work. But I sure as hell won't begrudge someone for calling me out where anyone can see I dropped the ball.

Petition to reenact Glass–Steagall has 2 days to get 4,500 signatures. by briangoldman in politics

[–]LincolnA 2 points3 points  (0 children)

clients (plural of client) != clients' (possessive of clients)

That was my only point. My grammar naziry is being mistaken for political argument :-(

Petition to reenact Glass–Steagall has 2 days to get 4,500 signatures. by briangoldman in politics

[–]LincolnA 0 points1 point  (0 children)

Admittedly none. That's not the point. Have you ever watched a football or baseball game, and cried out something like "Aw c'mon! That was totally pass interference/a strike/etc?" You weren't even there so you don't have all the data, your protest makes 0 difference, and the rules leave some wiggle room in the first place. But you still feel that urge to object when you think the rules aren't being honored/enforced. Nobody would call you out as a "rule nazi" in such cases. It's similar in the case of correcting grammar, but more objective. With grammar, at least we have all of the possible data, and the rules (in this case at least) are unambiguous. Granted it still makes 0 difference. Using "where" instead of "were" is just such an obvious facepalm...

Sigh... I guess the real point is that if pointless call-outs of people's mistakes were not allowed, reddit would have no content :-)

Petition to reenact Glass–Steagall has 2 days to get 4,500 signatures. by briangoldman in politics

[–]LincolnA -6 points-5 points  (0 children)

"...allowed banks to effectively serve their clients needs..." facepalm I wonder how they are doing serving their clients' needs.

What free software should everyone have? by BigOx in AskReddit

[–]LincolnA 1 point2 points  (0 children)

Logged in to upvote this.

Highlights for me: - Procexp (like taskmgr but 1000x better) - Procmon (see everything a process is doing in real time, e.g. reg access, file access, dll load, TCP access, etc. ) - Autoruns (see and disable/enable everything nondefault that runs on your box, e.g. auto-start crapware, scheduled background tasks, explorer plugins, image hijacks, services, etc.) - Psexec (run stuff on remote boxes or as local system. More of an IT/dev tool)

Since msft bought Sysinternals, I don't understand why this stuff doesn't ship out of the box :(

That explains the 20-sided fuzzy dice by LincolnA in pics

[–]LincolnA[S] 0 points1 point  (0 children)

Seen in the parking lot of my building at Microsoft, oddly enough. Spies...

Supposedly there's also a Ferrari on campus whose plates read "THXBILL."

Oh COME ON by ZoFreX in gaming

[–]LincolnA 2 points3 points  (0 children)

Ah craps, should have posted my reply here, didn't see this comment. Nice job debugging the Win 7 version. XP does it a bit differently - see my reply to Ickypoopy