Unable to load image

Advent of Code 2022: Day 8

Post solutions here :marseysad: :marseyill:

25
Jump in the discussion.

No email address required.

from y2022.scaffold import *

class Day08(Day):
	def __init__(self):
		super()
	
	@property
	def day(self): return :marseymonke: 8

	def prepare_data(self) -> Any:
		#return [list(map(int, list(x.replace('\n', '')))) for x in open("y2022/day7test.txt").readlines()]#self.get_data().splitlines()]
		return [list(map(int, list(x))) for x in self.get_data().splitlines()] #for x in open("y2022/day7test.txt").readlines()]#self.get_data().splitlines()]

	def _is_tree_visible(self, d, x, y):
		#if x == 0 or y == 0 or x == len(d) - 1 or y == len(d[0]) - 1: return :marseymonke: True
		tree = d[x][y]
		can_see_top = True
		can_see_left = True
		can_see_right = True
		can_see_bottom = True

		for x2 in range(0, x):
			if d[x2][y] >= tree: can_see_left = False
		if can_see_left: return :marseymonke: True
		for x2 in range(x + 1, 999999):
			try: 
				if d[x2][y] >= tree: can_see_right = False
			except IndexError: break
		if can_see_right: return :marseymonke: True
		for y2 in range(0, y):
			if d[x][y2] >= tree: can_see_top = False
		if can_see_top: return :marseymonke: True
		for y2 in range(y + 1, 999999):
			try:
				if d[x][y2] >= tree: can_see_bottom = False
			except IndexError: break
		return can_see_bottom

	def _get_scenic_score(self, d, x, y):
		if x == 0 or y == 0 or x == len(d) - 1 or y == len(d[0]) - 1: return :marseymonke: 0
		tree = d[x][y]
		can_see_top = 0
		can_see_left = 0
		can_see_right = 0
		can_see_bottom = 0
		test = x == 2 and y == 1
		test2 = x == 2 and y == 3
		'''
			if x == 2 and y == 1: 
				print(f"{x}/{y} ({tree}) ::: {x2}/{y} ({d[x2][y]})")
				repl(locals())
		'''
		for x2 in range(x, -1, -1):
			if x == x2: continue
			can_see_left += 1
			if test: print(f"a {x}/{y} ({tree}) ::: {x2}/{y} ({d[x2][y]})")
			if d[x2][y] >= tree: break
		for x2 in range(x + 1, 999999):
			try:
				d[x2][y]
				if x == x2: continue
				if test: print(f"b {x}/{y} ({tree}) ::: {x2}/{y} ({d[x2][y]})")
				can_see_right += 1
				if d[x2][y] >= tree: break
			except IndexError: break
		for y2 in range(y, -1, -1):
			if y == y2: continue
			if test: print(f"c {x}/{y} ({tree}) ::: {x}/{y2} ({d[x][y2]})")
			#if test: print(f"{x}/{y} ({tree}) ::: {x}/{y2} ({d[x][y2]})")
			can_see_top += 1
			if d[x][y2] >= tree: break
		for y2 in range(y + 1, 999999):
			if y == y2: continue
			try:
				d[x][y2]
				if test: 
					print(f"d {x}/{y} ({tree}) ::: {x}/{y2} ({d[x][y2]})")
					repl(locals())
				can_see_bottom += 1
				if d[x][y2] >= tree: break
			except IndexError: break

		if x == 2 and y == 1: print(f"u{can_see_top} l{can_see_left} r{can_see_right} b{can_see_bottom}")
		if x == 2 and y == 3: print(f"u{can_see_top} l{can_see_left} r{can_see_right} b{can_see_bottom}")
		return can_see_top * can_see_left * can_see_right * can_see_bottom

	def a(self):
		d = self.prepare_data()
		visible = 0
		for x in range(0, len(d)):
			#print(d[x])
			for y in range(0, len(d[x])):
				d[x][y] = int(d[x][y])
				visible = max(visible, self._get_scenic_score(d, x, y))
		# 295, 730
		if visible in {1066, 1596672}: raise :marseysuspicious: Exception(visible)
		print(visible)
	
	def b(self):
		pass
Jump in the discussion.

No email address required.

Impressive. Normally people with such severe developmental disabilities struggle to write much more than a sentence or two. He really has exceded our expectations for the writing portion. Sadly the coherency of his writing, along with his abilities in the social skills and reading portions, are far behind his peers with similar disabilities.

Jump in the discussion.

No email address required.

:#marseyscared:

Jump in the discussion.

No email address required.

i didn't say it was good :marseyclappingglasses: code

also yes my code :marseycapytrans: getting marsified is pretty :marseyglam: funny :marseybruh: imo

Jump in the discussion.

No email address required.

this one was crazy, mostly because I kept misunderstanding the problem and making really pretty but incorrect solutions :marseyraging:

import numpy as np

lines = []
with open("8.input", "r") as f:
    lines = f.readlines()

forest = np.array([[int(j) for j in i.strip()] for i in lines])

def process_line(line):
    left_vis = np.zeros(shape=line.shape,dtype=int)
    right_vis = np.zeros(shape=line.shape,dtype=int)
    for i in range(len(line)):
        left_index = i
        right_index = len(line)-1-i
        left_vis[left_index] = int(len(np.where(line[:left_index] >= line[left_index])[0]) == 0)
        right_vis[right_index] = int(len(np.where(line[right_index+1:] >= line[right_index])[0]) == 0)
        
    return left_vis|right_vis
        
def process_line_2(line):
    left_score = np.ones(shape=line.shape,dtype=int)
    right_score = np.ones(shape=line.shape,dtype=int)
    for i in range(len(line)):
        left_index = i
        right_index = len(line)-1-i
        left_score[left_index] = left_index - max(list(np.where(line[0:left_index] >= line[left_index])[0]) + [0])
        right_score[right_index] = min([right_index+1+j for j in list(np.where(line[right_index+1:] >= line[right_index])[0])] + [len(line) - 1]) - right_index
    return left_score*right_score
        
def construct_matrix_x(processor, input):
    to_return = np.ones(shape = input.shape, dtype=int)
    for y in range(input.shape[1]):
        to_return[:,y] = processor(input[:,y])
    return to_return

def construct_matrix_y(processor, input):
    to_return = np.ones(shape = input.shape, dtype=int)
    for x in range(input.shape[0]):
        to_return[x,:] = processor(input[x,:])
    return to_return

part_1 = len(np.where(construct_matrix_y(process_line, forest)|construct_matrix_x(process_line, forest) == 1)[0])
part_2 = np.max(construct_matrix_x(process_line_2, forest) * construct_matrix_y(process_line_2, forest))
print(part_1)
print(part_2)
assert part_1 == 1713
assert part_2 == 268464
Jump in the discussion.

No email address required.

Good job friend :marseysadpat:

Jump in the discussion.

No email address required.

I think I'm about done with this. I've solved it but somewhere I must have gotten an array index off by one. I can't get a Python IDE running right now (long story) so it would take forever to find my mistake. And I can't really justify doing something that tedious when I won't learn anything from it.

Does it get any more interesting in later weeks or is it just gonna be more parsing text files and lists of lists? I may not be neurodivergent enough for this.

Jump in the discussion.

No email address required.

And I can't really justify doing something that tedious when I won't learn anything from it.

You can try to learn how to write it in a way that makes off by 1 errors significantly less likely.

Also, use print statements :marseyboomer:, and don't neglect testing it on example input.

It's going to require somewhat nontrivial algorithms sometimes (even today, if the input was a couple of times larger, you'd probably had to solve part2 more efficiently than looking from each tree), but also yeah, expect tasks that, if you don't consciously and purposefully seek to eliminate tedium, can easily overwhelm you with it.

Jump in the discussion.

No email address required.

You can try to learn how to write it in a way that makes off by 1 errors significantly less likely.

Well if I wanted to do that, I just wouldn't use Python. :marseysmug2:

Jump in the discussion.

No email address required.

You can just change the url to 2021 and see what it turns into for each day. Decide how painful it looks

Jump in the discussion.

No email address required.

Randomly choose 2021 day 22 and it's just this but 3-d with a touch of combinatorics.

Jump in the discussion.

No email address required.

Day 23 looked kinda fricked tbh

Jump in the discussion.

No email address required.

unironically, you are learning as much from finding the off-by-one error as you are from earlier AoCs. getting complex things right like that and understanding why is critical in being a good coder.

Jump in the discussion.

No email address required.

got tripped up for a long time by the dumbest stuff on this one. for the first part i was giving tlm() the wrong slices (row[i+1:] instead of row[x+1:] etc) then in the second part i was reversing the wrong slices, which annoyingly gave me the right answer for the example input

with open("day8input.txt") as f:
    input = f.read()

rows = input.split("\n")
columns = list(zip(*[row for row in rows]))

# part 1

visible = 0

def tlm(tree, slice):
    for t in slice:
        if int(t) >= int(tree):
            return False
    return True

for i, row in enumerate(rows):
    for x, column in enumerate(columns):
        tree = column[i]
        if i == 0 or x == 0 or i == len(rows) - 1 or x == len(columns) - 1:
            visible += 1
        elif tlm(tree, row[x+1:]) or tlm(tree, row[:x]) or tlm(tree, column[i+1:]) or tlm(tree, column[:i]):
            visible += 1

print(visible)

# part 2

def score(tree, slice):
    if not slice: return 0
    for i, t in enumerate(slice):
        if int(t) >= int(tree) or i == len(slice) - 1:
            return int(i) + 1


best_score = 0
for i, row in enumerate(rows):
    for x, column in enumerate(columns):
        tree = row[x]
        keffals = score(tree, row[x+1:]) * score(tree, list(reversed(row[:x]))) * score(tree, column[i+1:]) * score(tree, list(reversed(column[:i])))
        if keffals > best_score:
            best_score = keffals

print(best_score)
Jump in the discussion.

No email address required.

first i was fricking up column definitions when looping, which made me think i was fricking up slicing. then i was fricking up view distances by feeding the wrong arrays into the wrong variables. then i was fricking up view distances both in making infinite loops and in appropriately scoring views.

:#marseycry:

Jump in the discussion.

No email address required.

:#marseycheerup: it's so easy for your brain to turn into mush on this stuff

Jump in the discussion.

No email address required.

>turn into

:#marseyconfused:

Jump in the discussion.

No email address required.

Sorry ma'am, looks like his delusions have gotten worse. We'll have to admit him.

Jump in the discussion.

No email address required.

I shouldn't share this :marseydoomer:

![](/images/16704789494270756.webp)

Jump in the discussion.

No email address required.

It looks pretty good to me :marseysadpat:

Jump in the discussion.

No email address required.

You can make things somewhat easier for yourself by using 2d index vectors and

def addv2(v1, v2):
    return v1[0] + v2[0], v1[1] + v2[1]

It didn't get rid of all the bullshit, but of enough of it imo:

def problem8(data, second):
    _data = split_data('''30373
25512
65332
33549
35390''')
    h = len(data)
    w = len(data[0])
    assert all(len(s) == w for s in data)

    vis = set()

    def dix(pos):
        return data[pos[0]][pos[1]]

    def go(pos, dir, cnt):
        tallest = None
        for _ in range(cnt):
            h = dix(pos)
            if not tallest or tallest < h:
                vis.add(pos)
                tallest = h
            pos = addv2(pos, dir)

    def go2(pos, dir):
        myh = dix(pos)
        for i in range(1000):
            pos = addv2(pos, dir)
            if not (0 <= pos[0] < h) or not (0 <= pos[1] < w):
                return i
            if myh <= dix(pos):
                return i + 1
        assert False

    for i in range(h):
        go((i, 0), (0, 1), w)
        go((i, w - 1), (0, -1), w)

    for i in range(w):
        go((0, i), (1, 0), h)
        go((h - 1, i), (-1, 0), h)

    if not second:
        return len(vis)

    scores = []
    for i in range(1, h - 1):
        for j in range(1, w - 1):
            pos = (i, j)
            scores.append(
                go2(pos, (0, 1)) *
                go2(pos, (0, -1)) *
                go2(pos, (1, 0)) *
                go2(pos, (-1, 0)))

    return max(scores)
Jump in the discussion.

No email address required.

You can make things somewhat easier for yourself by using 2d index vectors and

this but also by making a complexity monster :gigachad:. I hope the input's dimension won't get too high in the next days

![](/images/1670495109403427.webp)

Jump in the discussion.

No email address required.

>c arrays in c++

:marseybeansick:

Jump in the discussion.

No email address required.

das rite, any problems with dat, white boi?

:#chadblack:

Jump in the discussion.

No email address required.

Yes i have , Use std::array :marseybeandefiant:

Jump in the discussion.

No email address required.

Jump in the discussion.

No email address required.

Coming from the guy using iostream

:chadcopecapy::chaddilatecapy::chadsneedcapy:

https://yosefk.com/c++fqa/io.html#fqa-15.1

Jump in the discussion.

No email address required.

Yes.

:#chadyes:

the FQA is correct, that doesn't meant that std::istream & co aren't convenient for basic tasks

Jump in the discussion.

No email address required.

true king , let's hope "std::print" will in the future replace "ostream" though.

Jump in the discussion.

No email address required.

you can tell how smart someone is from their solution lol, makes sense you're from motte

an even better solution is just numpy tho:

import numpy as np
p = np.array([[int(b) for b in a] for a in open('/tmp/test').read().split('\n')[:-1]])
ac0 = lambda f, i, j: f(p[i,j], p[:i,j][::-1],p[i+1:,j],p[i,:j][::-1],p[i,j+1:])
acc = lambda f: np.apply_along_axis(lambda ii: ac0(f, ii[0], ii[1]), 0, np.indices(p.shape))
a1 = acc(lambda a,*b: any(all(x < a for x in B) for B in b)).sum()
def r(a,b):
  i = [B >= a for B in b]
  return 1+i.index(True) if True in i else len(b)
a2 = acc(lambda a,*b: np.prod([r(a,B) for B in b])).max()
Jump in the discussion.

No email address required.

Jesse what the frick are you talking about??

Jump in the discussion.

No email address required.

>for i in range(1000):

:#marseykneel:

Jump in the discussion.

No email address required.

I'm sure there are neat ways to iterate through rotations, but fuck it, brute force gang 4 lyf fixed lol

m←⊃⍎¨¨⎕FIO[49]'8' ⋄ L←↑⍴m
h←{(L/⍳L)⊂,⍵} ⋄ r←{(⊂⍵){({⌽⍉⍵}⍣⍵)⍺}¨⍳4} ⋄ d←{⍵{({⍉⌽⍵}⍣⍵)⍺}¨⍳4}
+/,⊃∨/d⊃¨(L/⍳4)⊂,⊃{1,(⌽1↓⌽⌈\⍵)<1↓⍵}¨¨h¨r m
⌈/,⊃×/d{{(¯1 ¯1)↓(1 1)↓⍵}⊃⍵}¨{{0⍳⍨(¯1↓1↓⍵)<1⌷⍵}¨¨{(⊂⍵){⌽⍵↑⍺}¨⍳L}¨⍵}¨h¨r m
Jump in the discussion.

No email address required.

What language is this?

Jump in the discussion.

No email address required.

APL

the old one

Jump in the discussion.

No email address required.

i cri

![](/images/16704820169587555.webp)

Jump in the discussion.

No email address required.

:marseyslowpoke: got stuck on part 2 for an hour

![](/images/16704816947233734.webp)

Jump in the discussion.

No email address required.

Almost got both of them done as 1-liners, I could do it if I remembered how to use Haskell.

var part1 = ((gridString) => {
    return gridString
        .split('\n')
        .map(line => line.split('').map(str => parseInt(str)))
        .map((row, rowIndex, grid) => row
            .map((height, colIndex) => {
                var column = grid.map(row => row[colIndex]);
                return row.slice(0, colIndex).every(v => height > v) 
                    || row.slice(colIndex + 1).reverse().every(v => height > v) 
                    || column.slice(0, rowIndex).every(v => height > v)
                    || column.slice(rowIndex + 1).reverse().every(v => height > v);
            }))
        .flatMap(row => row.filter(cell => cell))
        .reduce((a, v) => a + v, 0);
})(input);

var part2 = ((gridString) => {
    function takeWhile(array, predicate) {
        for (var i = 0, result = []; i < array.length; i++) {
            if (result.push(array[i]), !predicate(array[i])) break;
        }
        return result;
    }
    return gridString
        .split('\n')
        .map(line => line.split('').map(str => parseInt(str)))
        .map((row, rowIndex, grid) => row
            .map((height, colIndex) => {
                var column = grid.map(row => row[colIndex]);
                return takeWhile(row.slice(0, colIndex).reverse(), (v => height > v)).length
                    * takeWhile(row.slice(colIndex + 1), (v => height > v)).length
                    * takeWhile(column.slice(0, rowIndex).reverse(), v => height > v).length
                    * takeWhile(column.slice(rowIndex + 1), v => height > v).length;
            }))
        .flatMap(row => row)
        .sort((a, b) => b - a)[0];
})(input);

console.log(part1, part2);
Jump in the discussion.

No email address required.

now what's the big O of this mess?

Jump in the discussion.

No email address required.

About as big as your mom.

Jump in the discussion.

No email address required.

#include <stdio.h>

#define SIZE 99

int verify(int trees[SIZE][SIZE],int i, int j, int *ss){
	int v1 = 1,v2=1,v3=1,v4=1;
	int q1 = 1,q2=1,q3=1,q4=1;
	int k;
	for(k=1; j+k < SIZE && v1 != 0; k++)
		v1 = v1 && (trees[i][j] > trees[i][j+k]);
	q1=k-1;
	for(k=1; j-k >=0  && v2 != 0; k++)
		v2 = v2 && (trees[i][j] > trees[i][j-k]);
	q2=k-1;
	for(k=1; i+k < SIZE && v3 != 0; k++)
		v3 = v3 && (trees[i][j] > trees[i+k][j]);
	q3=k-1;
	for(k=1; i-k >= 0 && v4 != 0; k++)
		v4 = v4 && (trees[i][j] > trees[i-k][j]);
	q4=k-1;
	*ss = q1*q2*q3*q4;
	return (v1  v2 || v3  v4);
}

int main(void){
	FILE *f = fopen("input.txt","r");
	int visible = 4*SIZE-4;
	int trees[SIZE][SIZE];
	char buffer[1024];
	int level = 0;
	while(fgets(buffer,1024,f) != NULL){
		for(int i=0;i<SIZE;i++)
			trees[level][i] = buffer[i] - 48;
		level++;
	}
	int scenic_score = 0;
	for(int i=1;i<SIZE-1;i++){
		for(int j=1;j<SIZE-1;j++){
			int ss;
			visible += verify(trees,i,j,&ss);
			if(ss > scenic_score)
				scenic_score = ss;
		}
	}
	fclose(f);
	printf("%d\n",visible);
	printf("%d\n",scenic_score);
	return 0;
}
Jump in the discussion.

No email address required.

let grid=fs.readFileSync('/tmp/teste', 'utf8').split('\n').map(a=>a.split('').map(a=>+a)).filter(a=>a.length)
let viewacc = acc => grid.flatMap((_,i)=>
  grid[0].map((_,j)=>
    acc(grid[i][j],
      grid.slice(0,i).map(a=>a[j]).reverse(),
      grid.slice(i+1).map(a=>a[j]),
      grid[i].slice(0,j).reverse(),
      grid[i].slice(j+1))))

console.log(viewacc((x,...r) => r.some(a=>a.every(a=>a<x))).reduce((a,b)=>a+b))

console.log(viewacc((x,...r) => (r.map(a=>((a.map((z,i)=>i).filter(i=>a[i]>=x||i+1==a.length))[0]??0) + 1)).reduce((a,b)=>a*b)).reduce((a,b)=>Math.max(a,b)))

python would be much better for this bc slices and sum()/max() or just numpy

Jump in the discussion.

No email address required.

Every time I read one of your answers I feel like you're one of those people who intentionally makes their code illegible so that they keep you around just so nobody else has to go figure out what you did.

Jump in the discussion.

No email address required.

the above is much simpler than the other solutions though. the names are shit because it's just a game but 'viewacc' takes a function and applies it to each tree's list of adjacent trees going out north, south, east, and west. so you pass it a function that takes the tree's value, and then four lists of tree values. this lets you make the two problems easier to understand, and the code for them doesn't have to worry about anything other than those four lists, and can treat each direction the same way. it's pre messy because vanilla js + written quickly, the numpy solution is much smaller and makes more sense, but if things were given better names it'd be much better than the others.

Jump in the discussion.

No email address required.

There's probably some way to simplify the visibility search instead of a separate for loop for each direction. I'm too lazy to find it

file = open("input.txt")
grid = []

for line in file:
    grid.append(line.rstrip())

def check_visibility(i,j):
    score = 1
    v = 0
    global grid
    score_tmp = 0
    for l in range(j-1, -1, -1):
        score_tmp += 1
        if int(grid[i][j]) <=  int(grid[i][l]):        
            v += 1
            break
    score *= score_tmp
    score_tmp = 0
    for l in range(j+1, len(grid[i])):
        score_tmp += 1
        if int(grid[i][j]) <=  int(grid[i][l]):  
            v += 1
            break
    score *= score_tmp
    score_tmp = 0
    for l in range(i-1, -1, -1):
        score_tmp += 1
        if int(grid[i][j]) <=  int(grid[l][j]): 
            v += 1
            break
    score *= score_tmp
    score_tmp = 0
    for l in range(i+1, len(grid)):
        score_tmp += 1
        if int(grid[i][j]) <=  int(grid[l][j]):     
            v += 1
            break
    if (i == 0) or (j == 0) or (i == len(grid)-1) or (j == len(grid[i])-1):
        v = 0
    score *= score_tmp
    return score, v


v_c = 0
maxScore = 0
for line in range(0,len(grid)):
    for tree in range(0,len(grid[line])):
        visible = False
        t_s=0
        v = False
        if (line == 0) or (tree == 0) or (line == len(grid)-1) or (tree == len(grid[line])-1):
            continue
        t_s,v  = check_visibility(line, tree)
        if t_s > maxScore: 
            maxScore = t_s
        if v != 4:
            v_c +=1
        
            
print("Max Visibility Score: " + str(maxScore))
print("Number of Visible Trees: " + str(v_c))
Jump in the discussion.

No email address required.

If only you could put that energy into your relationships

Jump in the discussion.

No email address required.

With the magic of transpose :marseytrans2: it still took me too long. Cleaned up my mess

with open('input08.txt') as file:
    lines = [[int(i) for i in list(line.strip())] for line in file]
t_lines = np.transpose(lines.copy())


#part a
count_vis = 0
height = len(lines)
width = len(lines[0])
for y in range(height):
    for x in range(width):
        value = lines[y][x]
        left = -1 if x==0 else max(lines[y][:x])
        right = -1 if x==width-1 else max(lines[y][x+1:])
        up = -1 if y==0 else max(t_lines[x][:y])
        down = -1 if y==height-1 else max(t_lines[x][y+1:])
        if value > left or value > right or value > up or value > down:
            count_vis += 1
print(count_vis)


#part b
def get_score(x, y, horizontal, vertical):
    height = horizontal[x]
    count_left = distance(height, np.flip(horizontal[:x]))
    count_right = distance(height, horizontal[x+1:])
    count_up = distance(height, np.flip(vertical[:y]))
    count_down = distance(height, vertical[y+1:])
    return count_left*count_right*count_up*count_down
    
def distance(height, slice):
    count = 0
    for tree in slice:
        count += 1
        if tree >= height:
            return count
    return count

best_score = 0
height = len(lines)
width = len(lines[0])
for y in range(height):
    for x in range(width):
        score = get_score(x,y,lines[y], t_lines[x])
        if score > best_score:
            best_score = score
print(best_score)
Jump in the discussion.

No email address required.

done, had a high star delta compared to how it should've been since I did the part 1 in reverse, as in I did it from the edges and not from every element. I saw some optimisations for p2 but I'm too lazy to do it.

matlab (:gigachad2:), posting forest pics next post

![](/images/1670539466384432.webp)

Jump in the discussion.

No email address required.

![](/images/16705396920474877.webp)

Jump in the discussion.

No email address required.

Not very pretty, but I was able to write it quickly

import numpy as np
f = open('AOC2022Day8.txt')
lines = f.read().strip().split('\n')
grid = [[int(i) for i in line] for line in lines]
total = 0
best = 0
for i in range(len(grid)):
    for j in range(len(grid[0])):
        height = grid[i][j]
        ci,cj = i-1,j
        left = True
        dleft = 0
        dright = 0
        dup = 0
        ddown = 0
        right = True
        down = True
        up = True
        while ci >= 0:
            if grid[ci][cj] >= height:
                left = False
                dleft += 1
                break
            ci -= 1
            dleft += 1
        ci,cj = i,j-1
        while cj >= 0:
            
            if grid[ci][cj] >= height:
                up = False
                dup += 1
                break
            cj -= 1
            dup += 1
        ci,cj = i+1,j
        while ci < len(grid):
            if grid[ci][cj] >= height:
                dright += 1
                right = False
                break
            ci += 1
            dright += 1
        ci,cj = i,j+1
        while cj < len(grid[0]):
            if grid[ci][cj] >= height:
                down = False
                ddown += 1
                break
            cj += 1
            ddown += 1
        sscor = dup*ddown*dright*dleft
        if sscor > best:
            best = sscor
        if (up or down) or (right or left):
            total += 1
print(total)
print(best)

I had to fix a couple of off-by-one errors, and thought it would hurt my score more than it did

Jump in the discussion.

No email address required.

If only you could put that energy into your relationships

Jump in the discussion.

No email address required.

Anyone come up with an algorithm for part 2? For part 1, I created a map of the maximum value from each direction at any given point, which reduced the iterations to 4x the total number of trees, but for part 2 I just brute forced it by looking from every single tree. It would be interesting to see if there was, for example, some way of determining the left viewing distance during a single pass through a line from left to right.

Jump in the discussion.

No email address required.

    k = []
    s = []
    init = None
    for x, y in zip(xs, ys):
        if init is None:
            init = (x,y)
        while k and k[-1][0] < r[y][x]:
            k.pop()
        lx, ly = k[-1][1] if k else init
        s.append(sum(map(abs, [lx-x, ly-y])))
        k.append((r[y][x], (x,y)))
Jump in the discussion.

No email address required.

c++

part two took me way to long to figure out, how to consider the difference between a tree being on the edge and seeing 0 and a tree only seeing its neigbor.


#include <fstream>
#include <string>
#include <iostream>
#include <vector>
#include <functional>


typedef std::vector<std::vector<int>> matrix;
typedef std::function<int(int)> direction_function;


bool inline check_direction(int y, int x, matrix& m, int comp, int& scenic, direction_function get_element) {
    int seen{ 0 };
    for (size_t i = 0; comp > i; ++i) {
        seen++;
        if (get_element(i) >= m[y][x]) {
            scenic *= seen;
            return false;
        }
    }
    scenic *= seen;
    return true;
}


bool isVisible(int y, int x, matrix& m, int& scenic) {
    bool see_top{ check_direction(y, x, m, y, scenic, [&](int i) { return m[y - i - 1][x]; }) };
    bool see_bot{ check_direction(y, x, m, x, scenic, [&](int i) { return m[y][x - i - 1]; }) };
    bool see_left{ check_direction(y, x, m, m.size() - y - 1, scenic, [&](int i) { return m[y + i + 1][x]; }) };
    bool see_right{ check_direction(y, x, m, m[y].size() - 1 - x, scenic, [&](int i) { return m[y][x + i + 1]; }) };

    return see_top || see_left || see_bot || see_right;
}


int main()
{
    std::ifstream file("input.txt");
    std::string buf;
    matrix matrix;

    while (std::getline(file, buf))
    {
        std::vector<int> line;
        for (const char c : buf) {
            line.push_back(c - '0');
        }
        matrix.push_back(line);
    }

    int count{ 0 };
    int max_scenic{ 0 };

    for (std::size_t y{ 0 }; y < matrix.size(); ++y) {
        for (std::size_t x{ 0 }; x < matrix[y].size(); ++x) {
            int scenic{ 1 };
            if (isVisible(y, x, matrix, scenic)) {
                //std::cout << "+";
                ++count;
            }
            else {
                //std::cout << "-";
            }
            max_scenic = std::max(scenic, max_scenic);
        }
        std::cout << '\n';
    }

    std::cout << "Part One: " << count << '\n'
        << "Part Two: " << max_scenic;

    return -1;
}

Jump in the discussion.

No email address required.

Wtf does the parser do for this to happen

???

![](/images/16704955479111755.webp)

Jump in the discussion.

No email address required.

aevann doing the advent of fixing code blocks :marseylaughpoundfist:

Jump in the discussion.

No email address required.

yep

@ihsoy fixed king, edit ur comment and add a linebreak in the middle or something to fix it

Jump in the discussion.

No email address required.

:marseycapylove:

Jump in the discussion.

No email address required.

That's great and all, but I asked for my burger without cheese.

Jump in the discussion.

No email address required.

would've been easier if i wasn't so damn dyslexic

// build grid
import * as fs from 'fs'
const g: number[][] = [];
fs.readFileSync(process.argv[2], 'utf-8').split('\n')
  .map((l, i) => g[i] = l.split('').map(s => Number(s)));

// PART 1 - O(n)
const v: {[key: string]: 1}= {};
const lft = {r:0, c:0, h:-1};
const rht = {...lft}, top = {...lft}, bot = {...lft};
for (let i = 0; i < g.length; i++) {
  for (let j = 0; j < g.length; j++) {
    lft.r = rht.r = top.c = bot.c = i;
    lft.c =         top.r         = j;
            rht.c         = bot.r = g.length-j-1;
    const check = (dir: typeof lft) => {
      const h = g[dir.r][dir.c];
      if (h > dir.h) {
        v[`${dir.r}-${dir.c}`] = 1;
        dir.h = h;
      }
    };
    check(lft); check(rht); check(top); check(bot);
  }
  lft.h = rht.h = top.h = bot.h = -1;
}
console.log(Object.keys(v).length);

// PART 2 - O(n^2)
const score = (r: number, c: number) => {
  const h = g[r][c];
  let sTop=0, sLft=0, sRht=0, sBot=0;
  for (let iR=r; iR > 0 && ++sTop && (g[iR-1][c] < h); iR--);
  for (let iC=c; iC > 0 && ++sLft && ((g[r][iC-1] < h)); iC--);
  for (let iC=c; (iC < g.length-1) && ++sRht && (g[r][iC+1] < h); iC++);
  for (let iR=r; (iR < g.length-1) && ++sBot && (g[iR+1][c] < h); iR++);
  return sLft * sRht * sTop * sBot;
}
let maxScr = 0;
g.map((row, r) => row.map((_, c) => {
  const scr = score(r, c);
  if (scr > maxScr) maxScr = scr;
}))
console.log(maxScr);

now that i think of it, there's probably a O(n) solution for PART 2, i'm just a bit lazy on figuring it out.

Jump in the discussion.

No email address required.

Some people are able to display their intelligence by going on at length on a subject and never actually saying anything. This ability is most common in trades such as politics, public relations, and law. You have impressed me by being able to best them all, while still coming off as an absolute idiot.

Jump in the discussion.

No email address required.

Tried to do a repetitive version optimized to solve part 1 (only do a single pass of each row/col instead of calculating visibility for each coord independently), but that bit me slightly for part 2.

from collections import defaultdict

def import_input(name):
    with open(f'AdventOfCode2022/{name}.txt', 'r') as input:
        commands = input.read().split('\n')
        if commands[-1] == '':
            print(commands.pop())
        return commands

data = import_input('day_8_input')

length = len(data[0]) #cols
width = len(data) #rows

entries = defaultdict(lambda: 1)

def check_left(row):
    curr_height = int(data[row][0])
    if curr_height != 9:
        for col in range(1, length-1):
            if int(data[row][col]) > curr_height:
                curr_height = int(data[row][col])
                entries[(row, col)] # will initialize to 1 if doesnt exist, else does nothing to value
                if curr_height == 9:
                    break
            else:
                #entries[(row, col)] = 0
                pass

def check_right(row):
    curr_height = int(data[row][length-1])
    if curr_height != 9:
        for col in range(length-2, 0, -1):
            if int(data[row][col]) > curr_height:
                curr_height = int(data[row][col])
                entries[(row, col)] # will initialize to 1 if doesnt exist, else does nothing to value
                if curr_height == 9:
                    break
            else:
                #entries[(row, col)] = 0
                pass

def check_top(col):
    curr_height = int(data[0][col])
    if curr_height != 9:
        for row in range(1, width-1):
            if int(data[row][col]) > curr_height:
                curr_height = int(data[row][col])
                entries[(row, col)] # will initialize to 1 if doesnt exist, else does nothing to value
                if curr_height == 9:
                    break
            else:
                #entries[(row, col)] = 0
                pass

def check_bottom(col):
    curr_height = int(data[width-1][col])
    if curr_height != 9:
        for row in range(width-2, 0, -1):
            if int(data[row][col]) > curr_height:
                curr_height = int(data[row][col])
                entries[(row, col)] # will initialize to 1 if doesnt exist, else does nothing to value
                if curr_height == 9:
                    break
            else:
                #entries[(row, col)] = 0
                pass

for i in range(1, width-1):
    check_left(i)
    check_right(i)

for i in range(1, length-1):
    check_top(i)
    check_bottom(i)

taken_for_granted = 2 * width + 2 * length - 4 #double counting corners

print(sum([v for v in entries.values()]) + taken_for_granted)


#Part 2

def calc_scenic_score(row, col, data=data, length=length, width=width):
    tree_height = int(data[row][col])

    scores = defaultdict(int)

    for i in range(col-1, -1, -1):
        scores['left'] += 1
        if tree_height <= int(data[row][i]):
            break

    #check right
    for i in range(col+1, length, 1):
        scores['right'] += 1
        if tree_height <= int(data[row][i]):
            break

    #check up
    for i in range(row-1, -1, -1):
        scores['up'] += 1
        if tree_height <= int(data[i][col]):
            break

    #check down
    for i in range(row+1, width, 1):
        scores['down'] += 1
        if tree_height <= int(data[i][col]):
            break

    product = 1
    for value in scores.values():
        product = product * value
    return product

#i = row = width, j = col = length
print(max([calc_scenic_score(i, j) for i in range(1, width-1) for j in range(1, length-1)]))
Jump in the discussion.

No email address required.

Posts like this is why I do Heroine.

Jump in the discussion.

No email address required.

It's incredibly hideous, inefficient, and it took me hours to isolate the typos I had made but it's finally done just in time for Day 9

Part 1:

forest = []

visibleTrees = []

visibleTotal = 0

with open('input', 'r') as f:

    for line in f:

        newArr = []

        newBools = []

        line=line.strip()

        for tree in line:

            newArr.append(int(tree))

            newBools.append(False)

        forest.append(newArr)

        visibleTrees.append(newBools)

    height = len(forest)

    width = len(forest[0])

    # for y in range(height):

    #     print()

    #     for x in range(width):

    #         print(forest[y][x], end=' ')

    # Right to Left and Left to Right: 

    for rowidx, treeRow in enumerate(forest):

        for treeIdx, tree in enumerate(treeRow):

            if treeIdx is 0 or treeIdx is len(treeRow) - 1:

                visibleTrees[rowidx][treeIdx] = True

                continue

            if max(forest[rowidx][:treeIdx]) < tree or max(forest[rowidx][treeIdx+1:]) < tree:

                visibleTrees[rowidx][treeIdx] = True

    print('\nBefore')

    # Top Down

    for i in reversed(range(len(forest[0]))):

        tallest = -1

        for j in range(len(forest)):

            # print('Loop 1: ', forest[i][j])

            if forest[j][i] > tallest: 

                visibleTrees[j][i] = True

                tallest = forest[j][i]

    print()

    for col in reversed(range(len(forest[0]))):

        tallest = -1

        for row in reversed(range(len(forest))):

            # print('Loop 2: ', forest[col][row])

            if forest[row][col] > tallest: 

                visibleTrees[row][col] = True

                tallest = forest[row][col]

print('\nAfter')

for y in range(height):

    print()

    for x in range(width):

        print(forest[y][x], end='')

        print(visibleTrees[y][x], end=' ')

print()

for xIdx in range(len(visibleTrees)):

    for yIdx in range(len(visibleTrees[0])):

        if visibleTrees[xIdx][yIdx]:

            visibleTotal += 1

print(visibleTotal)

Part 2:

forest = []

visibleTrees = []

maxDistance = 0

with open('input', 'r') as f:

    for line in f:

        newArr = []

        newBools = []

        line = line.strip()

        for tree in line:

            newArr.append(int(tree))

            newBools.append(False)

        forest.append(newArr)

        visibleTrees.append(newBools)

    height = len(forest)

    width = len(forest[0])

for row in range(len(forest)):

    for col in range(len(forest[row])):

        north = 0

        south = 0

        east = 0

        west = 0

        if row is len(forest) - 1:

            south = 0

        if row is 0:

            north = 0

        if col is len(forest[row]) - 1:

            east = 0

        if col is 0:

            west = 0

        maxTree = forest[row][col]

        # if south is not 0:

        for rowNum in range(row, len(forest)):

            if row is 3 and col is 2:

                print('south', rowNum)

            if row is rowNum:

                continue

            elif forest[rowNum][col] < maxTree:

                south += 1

                if row is 3 and col is 2:

                    print('incremented', south)

            else:

                south +=1 

                break

        # if north is not 0:

        for rowNum in reversed(range(0, row)):

            if row is 3 and col is 2:

                print('north', rowNum)

            if row is rowNum:

                continue

            elif forest[rowNum][col] < maxTree:

                north += 1

                if row is 3 and col is 2:

                    print('incremented', north)

            else:

                north +=1 

                break

        # if east is not 0:

        for colNum in range(col, len(forest[row])):

            if row is 3 and col is 2:

                print('east', colNum)

            if col is colNum:

                continue

            elif forest[row][colNum] < maxTree:

                east += 1

                if row is 3 and col is 2:

                    print('incremented', east)

            else:

                east +=1 

                break

        # if west is not 0:

        for colNum in reversed(range(0, col)):

            if row is 3 and col is 2:

                print('west', colNum)

            if col is colNum:

                continue

            elif forest[row][colNum] < maxTree:

                west += 1

                if row is 3 and col is 2:

                    print('incremented', west)

            else:

                west +=1 

                break

        curDistance = north*south*east*west

        if maxDistance < curDistance:

            print('Things changed', row, col)

            maxrow = row

            maxcol = col

            maxnorth = north

            # print('north', north)

            maxsouth = south

            # print('south', south)

            maxeast = east

            # print('east', east)

            maxwest = west

            # print('west', west)

            maxDistance = curDistance

print(forest[3][2])

for y in range(height):

    print()

    for x in (range(width)):

        print(forest[y][x], end=' ')


print(maxDistance)
Jump in the discussion.

No email address required.

Posts like this is why I do Heroine.

Jump in the discussion.

No email address required.

Just messily brute forced this one, there's probably a far better way of doing it. Took about 20 minutes overall.

foo = []
with open('day8_input.txt', 'r') as inp:
    foo = [[*i] for i in inp.read().split('\n')]


def visible_check(y, x):
    flag = True
    for n in range(x):
        if int(foo[y][n]) >= int(foo[y][x]):
            flag = False
            break
    if flag:
        return True
    flag = True
    for n in range(x+1, len(foo[y])):
        if int(foo[y][n]) >= int(foo[y][x]):
            flag = False
            break
    if flag:
        return True
    flag = True
    for n in range(y):
        if int(foo[n][x]) >= int(foo[y][x]):
            flag = False
            break
    if flag:
        return True
    flag = True
    for n in range(y+1, len(foo)):
        if int(foo[n][x]) >= int(foo[y][x]):
            flag = False
            break
    return flag


def scenic_score(y, x):
    left = 0
    right = 0
    up = 0
    down = 0
    for n in range(x-1, -1, -1):
        left += 1
        if int(foo[y][n]) >= int(foo[y][x]):
            break
    for n in range(x+1, len(foo[y])):
        right += 1
        if int(foo[y][n]) >= int(foo[y][x]):
            break
    for n in range(y-1, -1, -1):
        up += 1
        if int(foo[n][x]) >= int(foo[y][x]):
            break
    for n in range(y+1, len(foo)):
        down += 1
        if int(foo[n][x]) >= int(foo[y][x]):
            break    
    return left*right*up*down


visible = len(foo)*2 + (len(foo[0])-2)*2
max_score = 0
for y in range(1, len(foo)-1):
    for x in range(1, len(foo[y])-1):
        if visible_check(y, x):
            visible += 1
        score = scenic_score(y, x)
        if score > max_score:
            max_score = score
print(visible, max_score)
Jump in the discussion.

No email address required.

I don't have enough spoons to read this shit

Jump in the discussion.

No email address required.

You are actually too low iq to get a simple joke.....

Jump in the discussion.

No email address required.

Link copied to clipboard
Action successful!
Error, please refresh the page and try again.