kartoffelsaft

joined 1 year ago
[โ€“] [email protected] 5 points 5 months ago

Darn that sucks to hear. I was somewhat active several months ago. Unfortunately the server never hit "critical mass". My interest in any given game also waxes & wanes significantly so I know I kinda abruptly stopped playing.

[โ€“] [email protected] 8 points 7 months ago

I have mine set up with a bunch of categories that are sorted with a prepended 3-digit number. Allows me to have different sections of category without it getting mixed up. ex:

010 S
011 A+
012 A
013 A-
014 B+
etc...
350 plz play soon
355 wont play
...
800 dont remember buying this
[โ€“] [email protected] 4 points 11 months ago* (last edited 11 months ago)

Odin

When I read the problem description I expected the input to also be 2 digit numbers. When I looked at it I just had to say "huh."

Second part I think you definitely have to do in reverse (edit: if you are doing a linear search for the answer), as that allows you to nope out as soon as you find a match, whereas with doing it forward you have to keep checking just in case.

Formatted code

package day5

import "core:fmt"
import "core:strings"
import "core:slice"
import "core:strconv"

Range :: struct {
    dest: int,
    src: int,
    range: int,
}

Mapper :: struct {
    ranges: []Range,
}

parse_range :: proc(s: string) -> (ret: Range) {
    rest := s

    parseLen := -1

    destOk: bool
    ret.dest, destOk = strconv.parse_int(rest, 10, &parseLen)
    rest = strings.trim_left_space(rest[parseLen:])

    srcOk: bool
    ret.src, srcOk = strconv.parse_int(rest, 10, &parseLen)
    rest = strings.trim_left_space(rest[parseLen:])

    rangeOk: bool
    ret.range, rangeOk = strconv.parse_int(rest, 10, &parseLen)

    return
}

parse_mapper :: proc(ss: []string) -> (ret: Mapper) {
    ret.ranges = make([]Range, len(ss)-1)
    for s, i in ss[1:] {
        ret.ranges[i] = parse_range(s)
    }

    return
}

parse_mappers :: proc(ss: []string) -> []Mapper {
    mapsStr := make([dynamic][]string)
    defer delete(mapsStr)

    restOfLines := ss
    isLineEmpty :: proc(s: string)->bool {return len(s)==0}

    for i, found := slice.linear_search_proc(restOfLines, isLineEmpty); 
        found; 
        i, found  = slice.linear_search_proc(restOfLines, isLineEmpty) {
        
        append(&mapsStr, restOfLines[:i])
        restOfLines = restOfLines[i+1:]
    }
    append(&mapsStr, restOfLines[:])

    return slice.mapper(mapsStr[1:], parse_mapper)
}

apply_mapper :: proc(mapper: Mapper, num: int) -> int {
    for r in mapper.ranges {
        if num >= r.src && num - r.src < r.range do return num - r.src + r.dest
    }

    return num
}

p1 :: proc(input: []string) {
    maps := parse_mappers(input)
    defer {
        for m in maps do delete(m.ranges)
        delete(maps)
    }

    restSeeds := input[0][len("seeds: "):]
    min := 0x7fffffff

    for len(restSeeds) > 0 {
        seedLen := -1
        seed, seedOk := strconv.parse_int(restSeeds, 10, &seedLen)
        restSeeds = strings.trim_left_space(restSeeds[seedLen:])

        fmt.print(seed)
        for m in maps {
            seed = apply_mapper(m, seed)
            fmt.print(" ->", seed)
        }
        fmt.println()

        if seed < min do min = seed
    }

    fmt.println(min)
}

apply_mapper_reverse :: proc(mapper: Mapper, num: int) -> int {
    for r in mapper.ranges {
        if num >= r.dest && num - r.dest < r.range do return num - r.dest + r.src
    }

    return num
}

p2 :: proc(input: []string) {
    SeedRange :: struct {
        start: int,
        len: int,
    }

    seeds := make([dynamic]SeedRange)
    restSeeds := input[0][len("seeds: "):]

    for len(restSeeds) > 0 {
        seedLen := -1
        seedS, seedSOk := strconv.parse_int(restSeeds, 10, &seedLen)
        restSeeds = strings.trim_left_space(restSeeds[seedLen:])

        seedL, seedLOk := strconv.parse_int(restSeeds, 10, &seedLen)
        restSeeds = strings.trim_left_space(restSeeds[seedLen:])

        append(&seeds, SeedRange{seedS, seedL})
    }

    maps := parse_mappers(input)
    defer {
        for m in maps do delete(m.ranges)
        delete(maps)
    }

    for i := 0; true; i += 1 {
        rseed := i
        #reverse for m in maps {
            rseed = apply_mapper_reverse(m, rseed)
        }

        found := false
        for sr in seeds {
            if rseed >= sr.start && rseed < sr.start + sr.len {
                found = true
                break
            }
        }
        if found {
            fmt.println(i)
            break
        }
    }
}
[โ€“] [email protected] 1 points 11 months ago

Oh yeah, I misspoke, gonna edit.

[โ€“] [email protected] 1 points 11 months ago (1 children)

hmm, my code keeps getting truncated at for y in .., anyone have any idea why? Maybe the "<" right after that confuses a parser somewhere?

[โ€“] [email protected] 1 points 11 months ago* (last edited 11 months ago) (4 children)

Did this in Odin

Here's a tip: if you are using a language / standard library that doesn't have a set, you can mimic it with a map from your key to a nullary (in this case an empty struct)

formatted code

package day3

import "core:fmt"
import "core:strings"
import "core:unicode"
import "core:strconv"

flood_get_num :: proc(s: string, i: int) -> (parsed: int, pos: int) {
    if !unicode.is_digit(rune(s[i])) do return -99999, -1

    pos = strings.last_index_proc(s[:i+1], proc(r:rune)->bool{return !unicode.is_digit(r)})
    pos += 1

    ok: bool
    parsed, ok = strconv.parse_int(s[pos:])

    return parsed, pos
}

p1 :: proc(input: []string) {
    // wow what a gnarly type
    foundNumSet := make(map[[2]int]struct{})
    defer delete(foundNumSet)

    total := 0

    for y in 0..
[โ€“] [email protected] 3 points 11 months ago

Did mine in Odin. Found this day's to be super easy, most of the challenge was just parsing.

package day2

import "core:fmt"
import "core:strings"
import "core:strconv"
import "core:unicode"

Round :: struct {
    red: int,
    green: int,
    blue: int,
}

parse_round :: proc(s: string) -> Round {
    ret: Round

    rest := s
    for {
        nextNumAt := strings.index_proc(rest, unicode.is_digit)
        if nextNumAt == -1 do break
        rest = rest[nextNumAt:]

        numlen: int
        num, ok := strconv.parse_int(rest, 10, &amp;numlen)
        rest = rest[numlen+len(" "):]

        if rest[:3] == "red" {
            ret.red = num
        } else if rest[:4] == "blue" {
            ret.blue = num
        } else if rest[:5] == "green" {
            ret.green = num
        }
    }

    return ret
}

Game :: struct {
    id: int,
    rounds: [dynamic]Round,
}

parse_game :: proc(s: string) -> Game {
    ret: Game

    rest := s[len("Game "):]

    idOk: bool
    idLen: int
    ret.id, idOk = strconv.parse_int(rest, 10, &amp;idLen)
    rest = rest[idLen+len(": "):]

    for len(rest) > 0 {
        endOfRound := strings.index_rune(rest, ';')
        if endOfRound == -1 do endOfRound = len(rest)

        append(&amp;ret.rounds, parse_round(rest[:endOfRound]))
        rest = rest[min(endOfRound+1, len(rest)):]
    }

    return ret
}

is_game_possible :: proc(game: Game) -> bool {
    for round in game.rounds {
        if round.red   > 12 ||
           round.green > 13 ||
           round.blue  > 14 {
            return false
        }
    }
    return true
}

p1 :: proc(input: []string) {
    totalIds := 0

    for line in input {
        game := parse_game(line)
        defer delete(game.rounds)

        if is_game_possible(game) do totalIds += game.id
    }

    fmt.println(totalIds)
}

p2 :: proc(input: []string) {
    totalPower := 0

    for line in input {
        game := parse_game(line)
        defer delete(game.rounds)

        minRed   := 0
        minGreen := 0
        minBlue  := 0
        for round in game.rounds {
            minRed   = max(minRed  , round.red  )
            minGreen = max(minGreen, round.green)
            minBlue  = max(minBlue , round.blue )
        }

        totalPower += minRed * minGreen * minBlue
    }

    fmt.println(totalPower)
}
[โ€“] [email protected] 2 points 11 months ago

Did this in Odin (very hashed together, especially finding the last number in part 2):

spoiler

package day1

import "core:fmt"
import "core:strings"
import "core:strconv"
import "core:unicode"

p1 :: proc(input: []string) {
    total := 0

    for line in input {
        firstNum := line[strings.index_proc(line, unicode.is_digit):][:1]
        lastNum := line[strings.last_index_proc(line, unicode.is_digit):][:1]

        calibrationValue := strings.concatenate({firstNum, lastNum})
        defer delete(calibrationValue)

        num, ok := strconv.parse_int(calibrationValue)

        total += num
    }

    // daggonit thought it was the whole numbers
    /*
    for line in input {
        firstNum := line

        fFrom := strings.index_proc(firstNum, unicode.is_digit)
        firstNum = firstNum[fFrom:]

        fTo := strings.index_proc(firstNum, proc(r:rune)->bool {return !unicode.is_digit(r)})
        if fTo == -1 do fTo = len(firstNum)
        firstNum = firstNum[:fTo]


        lastNum := line
        lastNum = lastNum[:strings.last_index_proc(lastNum, unicode.is_digit)+1]
        lastNum = lastNum[strings.last_index_proc(lastNum, proc(r:rune)->bool {return !unicode.is_digit(r)})+1:]

        calibrationValue := strings.concatenate({firstNum, lastNum})
        defer delete(calibrationValue)

        num, ok := strconv.parse_int(calibrationValue, 10)
        if !ok {
            fmt.eprintf("%s could not be parsed from %s", calibrationValue, line)
            return
        }

        total += num;
    }
    */

    fmt.println(total)
}

p2 :: proc(input: []string) {
    parse_wordable :: proc(s: string) -> int {
        if len(s) == 1 {
            num, ok := strconv.parse_int(s)
            return num
        } else do switch s {
            case "one"  : return 1
            case "two"  : return 2
            case "three": return 3
            case "four" : return 4
            case "five" : return 5
            case "six"  : return 6
            case "seven": return 7
            case "eight": return 8
            case "nine" : return 9
        }

        return -1
    }

    total := 0

    for line in input {
        firstNumI, firstNumW := strings.index_multi(line, {
            "one"  , "1",
            "two"  , "2",
            "three", "3",
            "four" , "4",
            "five" , "5",
            "six"  , "6",
            "seven", "7",
            "eight", "8",
            "nine" , "9",
        })
        firstNum := line[firstNumI:][:firstNumW]


        // last_index_multi doesn't seem to exist, doing this as backup
        lastNumI, lastNumW := -1, -1
        for {
            nLastNumI, nLastNumW := strings.index_multi(line[lastNumI+1:], {
                "one"  , "1",
                "two"  , "2",
                "three", "3",
                "four" , "4",
                "five" , "5",
                "six"  , "6",
                "seven", "7",
                "eight", "8",
                "nine" , "9",
            })

            if nLastNumI == -1 do break

            lastNumI += nLastNumI+1
            lastNumW  = nLastNumW
        }
        lastNum := line[lastNumI:][:lastNumW]

        total += parse_wordable(firstNum)*10 + parse_wordable(lastNum)
    }

    fmt.println(total)
}

Had a ton of trouble with part 1 until I realized I misinterpreted it. Especially annoying because the example was working fine. So paradoxically part 2 was easier than 1.

[โ€“] [email protected] 4 points 1 year ago

I don't think this can really be answered until after the fact. Anything that I (and I suspect most) people could say about an artstyle are going to be particular to an instance of that artsyle. If I'd give advice as someone who is neither an artist nor a game designer, what attracts me more than anything is a unique artstyle, which, if I'm gonna give a brutal opinion, starting from a vague category like 'pixel', 'hand drawn' or '3D' probably won't get you there.

I feel like I even struggle to answer your question at face value because it doesn't align well at all with how I conceptualize game art. For example, Cruelty Squad is a game that I don't think I'd have gotten if not for it's artsyle. Like, sure, it's 3D, but it's a lot more like a PilotRedSun animation than it is a game like TF2. Or take a game like Factorio: most of the assets of that game are pre-rendered 3D sprites, so despite being artisticly unique in a way that interests me it doesn't fit into the categories you've asked about. The best I can say is "I dunno", and I don't think anyone else can answer it further than that.

[โ€“] [email protected] 4 points 1 year ago* (last edited 1 year ago) (1 children)

There is the Anno series of games, which are technically RTS games but if I'm honest I find them the most fun when I go out of my way to avoid combat/micromanagement. I've only played 1404, 2070, and 2205, 2070 being the best in my opinion, but it has a bad history with DRM so I'd suggest 1404 (known as "Dawn of Discovery" in the US because us americans are afraid of numbers apparently).

Edit: looking at the steam page it looks like they decided to take 1404 down and made a new page where the game is (mostly) unchanged besides requiring you to jump through all the BS hoops that 2070 did, so I'd say if you're gonna spend money get 1404 on GOG, or if you are willing to do unspeakable things go with 2070.

[โ€“] [email protected] 1 points 1 year ago

I just saw the second clue and realized the stuff I've been building might cause some misdirection. Guessing that clue will be harder to figure out than intended ๐Ÿคท.

[โ€“] [email protected] 3 points 1 year ago

To be fair, that post specifically asks people who don't have a technical background. It can be used to show that laymen have the capacity to use a federated platform like lemmy, but not that they are a significant portion of the userbase (albeit that post does have a lot of replies).

view more: โ€น prev next โ€บ