Software developer and artist.

  • 1 Post
  • 41 Comments
Joined 1 year ago
cake
Cake day: June 5th, 2023

help-circle



  • Nice and easy.

    Lua
    -- SPDX-FileCopyrightText: 2023 Jummit
    --
    -- SPDX-License-Identifier: GPL-3.0-or-later
    
    local function nums(str)
    	local res = {}
    	for num in str:gmatch("%d+") do
    		res[num] = true
    	end
    	return res
    end
    
    local cards = {}
    local points = 0
    for line in io.open("4.input"):lines() do
    	local winning, have = line:match("Card%s*%d+: (.*) | (.*)")
    	winning = nums(winning)
    	have = nums(have)
    	local first = true
    	local score = 0
    	local matching = 0
    	for num in pairs(have) do
    		if winning[num] then
    			matching = matching + 1
    			if first then
    				first = false
    				score = score + 1
    			else
    				score = score * 2
    			end
    		end
    	end
    	points = points + score
    	table.insert(cards, {have=have, wins=matching, count=1})
    end
    print(points)
    
    local cardSum = 0
    for i, card in ipairs(cards) do
    	cardSum = cardSum + card.count
    	for n = i + 1, i + card.wins do
    		cards[n].count = cards[n].count + card.count
    	end
    end
    print(cardSum)
    

  • Input parsing AGAIN?

    Lua
    -- SPDX-FileCopyrightText: 2023 Jummit
    --
    -- SPDX-License-Identifier: GPL-3.0-or-later
    
    local lines = {}
    for line in io.open("3.input"):lines() do
    	table.insert(lines, "."..line..".")
    end
    local width = #lines[1]
    local height = #lines
    local function at(x, y, w)
    	if y < 1 or y > height then return nil end
    	return lines[y]:sub(x, x + w - 1)
    end
    local sum = 0
    local gears = {}
    for y, line in ipairs(lines) do
    	local start = 1
    	local outLine = line
    	while true do
    		local newStart, numEnd = line:find("%d+", start)
    		if not newStart then break end
    		local symbol = false
    		local num = tonumber(line:sub(newStart, numEnd))
    		for y = y - 1, y + 1 do
    			local surrounding = at(newStart - 1, y, numEnd - newStart + 3)
    			if surrounding then
    				if surrounding and surrounding:match("[^.%d]") then
    					symbol = true
    				end
    				for i = 1, #surrounding do
    					local gear = surrounding:sub(i, i) == "*"
    					if gear then
    						if not gears[y] then
    							gears[y] = {}
    						end
    						local x = i + newStart - 2
    						if not gears[y][x] then
    							gears[y][i + newStart - 2] = {}
    						end
    						table.insert(gears[y][x], num)
    					end
    				end
    			end
    		end
    		if symbol then
    			sum = sum + num
    		end
    		start = numEnd + 1
    	end
    end
    print(sum)
    local ratio = 0
    for _, line in pairs(gears) do
    	for _, gears in pairs(line) do
    		if #gears == 2 then
    			ratio = ratio + gears[1] * gears[2]
    		end
    	end
    end
    print(ratio)
    
    Hare (Part one only)
    // SPDX-FileCopyrightText: 2023 Jummit
    //
    // SPDX-License-Identifier: GPL-3.0-or-later
    
    use strings;
    use regex;
    use fmt;
    use os;
    use bufio;
    use io;
    use strconv;
    use types;
    
    fn star_in(lines: []str, x: uint, y: uint, w: uint) bool = {
    	let start = y;
    	if (start > 0) start -= 1;
    	let end = y + 1;
    	if (end >= len(lines)) end -= 1;
    	const re = regex::compile(`[^.0-9]`)!;
    	for (let h = start; h <= end; h += 1) {
    		fmt::println(strings::sub(lines[h], x, x + w))!;
    		if (regex::test(&re, strings::sub(lines[h], x, x + w))) {
    			fmt::println("")!;
    			return true;
    		};
    	};
    	fmt::println("")!;
    	return false;
    };
    
    export fn main() void = {
    	const file = os::open("3.input")!;
    	defer io::close(file)!;
    	const buf = bufio::newscanner(file, types::SIZE_MAX);
    	let lines: []str = [];
    	defer strings::freeall(lines);
    	for (true) {
    		match (bufio::scan_line(&buf)!) {
    		case io::EOF =>
    			break;
    		case let line: const str =>
    			append(lines, strings::dup(line));
    		};
    	};
    	const height = len(lines);
    	const width = len(lines[0]);
    	let sum: uint = 0;
    	let gears: [](uint, uint) = [];
    	const num_re = regex::compile(`[0-9]+`)!;
    	for (let y = 0u; y < len(lines); y += 1) {
    		let nums = regex::findall(&num_re, lines[y]);
    		defer regex::result_freeall(nums);
    		for (let i = 0z; i < len(nums); i += 1) {
    			for (let j = 0z; j < len(nums[i]); j += 1) {
    				const find = nums[i][j];
    				const num = strconv::stou(find.content)!;
    				let start = find.start: uint;
    				let w = len(find.content): uint + 2;
    				if (start > 0) {
    					start -= 1;
    				} else {
    					w -= 1;
    				};
    				if (star_in(lines, start, y, w)) {
    					sum += num;
    				};
    			};
    		};
    	};
    	fmt::printfln("{}", sum)!;
    };
    

  • Mostly an input parsing problem this time, but it was fun to use Hares tokenizer functions:

    lua
    -- SPDX-FileCopyrightText: 2023 Jummit
    --
    -- SPDX-License-Identifier: GPL-3.0-or-later
    
    local colors = {"blue", "red", "green"}
    local available = {red = 12, blue = 14, green = 13}
    local possible = 0
    local id = 0
    local min = 0
    
    for game in io.open("2.input"):lines() do
      id = id + 1
      game = game:gsub("Game %d+: ", "").."; "
      local max = {red = 0, blue = 0, green = 0}
      for show in game:gmatch(".-; ") do
        for _, color in ipairs(colors) do
          local num = tonumber(show:match("(%d+) "..color))
          if num then
            max[color] = math.max(max[color], num)
          end
        end
      end
      min = min + max.red * max.blue * max.green
      local thisPossible = true
      for _, color in ipairs(colors) do
        if max[color] > available[color] then
          thisPossible = false
          break
        end
      end
      if thisPossible then
        possible = possible + id
      end
    end
    
    print(possible)
    print(min)
    
    hare
    // SPDX-FileCopyrightText: 2023 Jummit
    //
    // SPDX-License-Identifier: GPL-3.0-or-later
    
    use strconv;
    use types;
    use strings;
    use io;
    use bufio;
    use os;
    use fmt;
    
    const available: []uint = [12, 13, 14];
    
    fn color_id(color: str) const uint = {
    	switch (color) {
    	case "red" => return 0;
    	case "green" => return 1;
    	case "blue" => return 2;
    	case => abort();
    	};
    };
    
    export fn main() void = {
    	const file = os::open("2.input")!;
    	defer io::close(file)!;
    	const scan = bufio::newscanner(file, types::SIZE_MAX);
    	let possible: uint = 0;
    	let min: uint = 0;
    
    	for (let id = 1u; true; id += 1) {
    		const line = match(bufio::scan_line(&scan)!) {
    		case io::EOF =>
    			break;
    		case let line: const str =>
    			yield strings::sub(
    					line,
    					strings::index(line, ": ") as size + 2,
    					strings::end);
    		};
    		let max: []uint = [0, 0, 0];
    		let tok = strings::rtokenize(line, "; ");
    		for (true) {
    			const show = match(strings::next_token(&tok)) {
    			case void =>
    				break;
    			case let show: str =>
    				yield show;
    			};
    			const pairs = strings::tokenize(show, ", ");
    			for (true) {
    				const pair: (str, str) = match(strings::next_token(&pairs)) {
    				case void =>
    					break;
    				case let pair: str =>
    					let tok = strings::tokenize(pair, " ");
    					yield (
    						strings::next_token(&tok) as str,
    						strings::next_token(&tok) as str
    					);
    				};
    				let color = color_id(pair.1);
    				let amount = strconv::stou(pair.0)!;
    				if (amount > max[color]) max[color] = amount;
    			};
    		};
    		if (max[0] <= available[0] && max[1] <= available[1] && max[2] <= available[2]) {
    			fmt::printfln("{}", id)!;
    			possible += id;
    		};
    		min += max[0] * max[1] * max[2];
    	};
    	
    	fmt::printfln("{}", possible)!;
    	fmt::printfln("{}", min)!;
    };
    

  • Trickier than expected! I ran into an issue with Lua patterns, so I had to revert to a more verbose solution, which I then used in Hare as well.

    Lua:

    lua
    -- SPDX-FileCopyrightText: 2023 Jummit
    --
    -- SPDX-License-Identifier: GPL-3.0-or-later
    
    local sum = 0
    for line in io.open("1.input"):lines() do
      local a, b = line:match("^.-(%d).*(%d).-$")
      if not a then
        a = line:match("%d+")
        b = a
      end
      if a and b then
        sum = sum + tonumber(a..b)
      end
    end
    print(sum)
    
    local names = {
      ["one"] = 1,
      ["two"] = 2,
      ["three"] = 3,
      ["four"] = 4,
      ["five"] = 5,
      ["six"] = 6,
      ["seven"] = 7,
      ["eight"] = 8,
      ["nine"] = 9,
      ["1"] = 1,
      ["2"] = 2,
      ["3"] = 3,
      ["4"] = 4,
      ["5"] = 5,
      ["6"] = 6,
      ["7"] = 7,
      ["8"] = 8,
      ["9"] = 9,
    }
    sum = 0
    for line in io.open("1.input"):lines() do
      local firstPos = math.huge
      local first
      for name, num in pairs(names) do
        local left = line:find(name)
        if left and left < firstPos then
          firstPos = left
          first = num
        end
      end
      local last
      for i = #line, 1, -1 do
        for name, num in pairs(names) do
          local right = line:find(name, i)
          if right then
            last = num
            goto found
          end
        end
      end
      ::found::
      sum = sum + tonumber(first * 10 + last)
    end
    print(sum)
    
    

    Hare:

    hare
    // SPDX-FileCopyrightText: 2023 Jummit
    //
    // SPDX-License-Identifier: GPL-3.0-or-later
    
    use fmt;
    use types;
    use bufio;
    use strings;
    use io;
    use os;
    
    const numbers: [](str, int) = [
    	("one", 1),
    	("two", 2),
    	("three", 3),
    	("four", 4),
    	("five", 5),
    	("six", 6),
    	("seven", 7),
    	("eight", 8),
    	("nine", 9),
    	("1", 1),
    	("2", 2),
    	("3", 3),
    	("4", 4),
    	("5", 5),
    	("6", 6),
    	("7", 7),
    	("8", 8),
    	("9", 9),
    ];
    
    fn solve(start: size) void = {
    	const file = os::open("1.input")!;
    	defer io::close(file)!;
    	const scan = bufio::newscanner(file, types::SIZE_MAX);
    	let sum = 0;
    	for (let i = 1u; true; i += 1) {
    		const line = match (bufio::scan_line(&scan)!) {
    		case io::EOF =>
    			break;
    		case let line: const str =>
    			yield line;
    		};
    		let first: (void | int) = void;
    		let last: (void | int) = void;
    		for (let i = 0z; i < len(line); i += 1) :found {
    			for (let num = start; num < len(numbers); num += 1) {
    				const start = strings::sub(line, i, strings::end);
    				if (first is void && strings::hasprefix(start, numbers[num].0)) {
    					first = numbers[num].1;
    				};
    				const end = strings::sub(line, len(line) - 1 - i, strings::end);
    				if (last is void && strings::hasprefix(end, numbers[num].0)) {
    					last = numbers[num].1;
    				};
    				if (first is int && last is int) {
    					break :found;
    				};
    			};
    		};
    		sum += first as int * 10 + last as int;
    	};
    	fmt::printfln("{}", sum)!;
    };
    
    export fn main() void = {
    	solve(9);
    	solve(0);
    };
    









  • If this is how everyone would act in their daily life, you would see crime, theft and abuse on an unimaginable level. No, people don’t always do what benefits them “at every individual point”. We are social creatures, acting as a community where the individuals benefit from working together. Although this has been successfully undermined by capitalism and other hierarchies.

    This whole concept is also called, the Prisoner’s Dilemma, one of my favorite thought experiments because it shows how being rational can result in everyone being worse off.


  • Yes. The “tragedy of the commons” is a myth.

    Without any limits, individual cattle owners have an incentive to overgraze the land, destroying its value to everybody.

    This is factually false, because the land will be destroyed and individuals don’t benefit, not even in the short term. Commons work great (see open source software), but capitalism and power structures abuse and destroy them for short-term profit.


  • Interesting viewpoint, but I think the applications aren’t at fault: The operating system should ensure that the user has control of the computer at all times. I think you need to do three things to achieve that:

    1. Limit process RAM usage, so the system never has to swap
    2. Limit process CPU usage, so the system never stalls
    3. When drivers / the operating itself crash, revert into a usable state (this one is probably the most complex one)