scarecrw's recent activity

  1. Comment on Stremio is an impressive program in ~tech

    scarecrw
    Link
    I've heard of similar tools in the past and have always been a bit confused on their exact functionality. Maybe someone here can enlighten me: If using torrents to download, is it acting as its...

    I've heard of similar tools in the past and have always been a bit confused on their exact functionality. Maybe someone here can enlighten me:

    • If using torrents to download, is it acting as its own client, or does it use a separate application for that?
    • Where is it pulling magnet links/torrent files from, public trackers? If so, who is updating that public tracker list?
    • How does it handle getting metadata for media from different sources? When selecting something to watch, can you see a list of sources and the properties of each file?

    I can see the appeal of "media piracy, but you don't have to worry about the details", but the details have always seemed rather important.

    1 vote
  2. Comment on What quotes inspire you? in ~talk

    scarecrw
    Link
    Edsger Dijkstra There was a similar piece of advice I've heard before, something along the lines of I take the Djikstra quote with a similar meaning, but applied to yourself as an individual; it's...

    As a slow-witted human being I have a very small head and I had better learn to live with it and to respect my limitations and give them full credit, rather than to try to ignore them, for the latter vain effort will be punished by failure.

    • Edsger Dijkstra

    There was a similar piece of advice I've heard before, something along the lines of

    If your plan starts with "If everyone just..." then you don't have a plan. At no point in human history has everyone "just".

    I take the Djikstra quote with a similar meaning, but applied to yourself as an individual; it's not a lamentation for our inabilities, it's just a reminder never to make plans based on false perceptions of yourself.

    6 votes
  3. Comment on Reinventing notebooks as reusable Python programs in ~comp

    scarecrw
    Link
    I love the idea of notebooks, but have been confused by where they have and haven't become popular. I was first introduced to their use for data analysis, mostly by non-programmers, and in that...

    I love the idea of notebooks, but have been confused by where they have and haven't become popular. I was first introduced to their use for data analysis, mostly by non-programmers, and in that context their popularity seemed to stem from being a friendlier environment than a traditional write-compile-test-iterate workflow. I don't know how it got popular in the ML world, perhaps just as an extension of data analysis? The article mentions it being "the only programming environment that let you see your data while you worked on it", but that seems like an overstatement.

    Regardless, I'd love to see them used more as a way to bridge the programmer vs non-programmer gap. It's a great way to share mixed-level content, where those with experience with programming can see and tinker with the document, and those without can still read a narrative and see the results. I haven't seen it yet, but I would love to see something like Wolfram notebooks become a standard format for math textbooks or similar.

    5 votes
  4. Comment on How ‘talk pedometers’ are transforming education in Birmingham, US classrooms in ~tech

    scarecrw
    Link
    I had the chance to try a related tool a couple of years back. I was teaching online, so there wasn't any need for vests, the meeting was just recorded and afterwards it was processed to identify...

    I had the chance to try a related tool a couple of years back. I was teaching online, so there wasn't any need for vests, the meeting was just recorded and afterwards it was processed to identify speaking time, key interactions, and perhaps some other information I'm forgetting.

    I can't say it was enlightening me to anything I wasn't already aware of (I always kick myself after a lesson where I know I was talking too much), but seeing the data laid out and knowing it was being recorded definitely made me more attuned to this in the moment.

    I would have concerns using this continuously, as treating the natural back-and-forth of discussion as a metric seems like a doomed endeavor (Goodhart's law), but I can see it being an effective reminder if given to teachers as a tool for insight rather than an assessment.

    3 votes
  5. Comment on Wu-Tang Clan x Mathematics - Mandingo (2025) in ~music

    scarecrw
    Link Parent
    Never checked out his others, but Black Gold was what first got me interested in Wu Tang. Absolutely blew my mind when I first heard it, and made me wonder why I hadn't seen more mashups/collabs...

    Never checked out his others, but Black Gold was what first got me interested in Wu Tang. Absolutely blew my mind when I first heard it, and made me wonder why I hadn't seen more mashups/collabs like that. I'll have to look at the Beatles mashup!

    3 votes
  6. Comment on Internationalization Puzzles in ~comp

    scarecrw
    Link
    I'm a sucker for puzzles, especially those that motivate learning, so this was a great find for me! It's an ongoing set of programming puzzles (à la advent of code) designed to emphasize the...

    I'm a sucker for puzzles, especially those that motivate learning, so this was a great find for me! It's an ongoing set of programming puzzles (à la advent of code) designed to emphasize the challenges of internationalization.

    I'm certainly guilty of brushing aside internationalization, "oh, nobody's actually going to access this in other languages", and part of that comes from my own lack of experience dealing with these topics. If you're in a similar spot, the first couple of puzzles are out and worth a try!

    6 votes
  7. Comment on I used to teach students. Now I catch ChatGPT cheats. in ~tech

    scarecrw
    Link
    I work with students, but not in a scenario where I'm faced with these challenges directly (I don't focus on written work nor am I grading assignments). I do, however, get to see and hear how they...

    I work with students, but not in a scenario where I'm faced with these challenges directly (I don't focus on written work nor am I grading assignments). I do, however, get to see and hear how they interact with ChatGPT and similar tools and have come away with a couple of insights:

    • Most of them use these tools very poorly. Students are mostly unaware of the strengths and weaknesses of LLMs, and, if the response they get isn't immediately useful, they give up quickly. This paper lays out this difficulty more clearly and formally than I ever could. Ultimately, this makes me very wary of any suggestion that students are going to have success in using these as learning aids, at least not without substantial guidance.

    • Students are very aware of others using these tools to cheat, and it's worsening the already enormous academic pressure many students feel. While I've only had a few students confess to their own usage of these tools, many are eager to complain about their classmates' cheating and how they feel their own work is being devalued as a result.

    I think the only thing in this piece that I see differently than the author, is how large or small of a shift this really is.

    I once believed my students and I were in this together, engaged in a shared intellectual pursuit.

    Really? I don't want to sound overly negative, but come on... Students doing the bare minimum to get a passing grade is not some new phenomenon. I suppose the accessibility of these new tools has laid bare just how many students are willing to take the easier path, but the connection between educational achievement and career success has long undermined the idea that schools could be so pure in their ideals.

    My optimistic vision for the future of student writing is focused on deep investigation of topics and, to put it bluntly, student ego. One sad commonality I've found in student work is an utter lack of pride. It's so beaten into students that the purpose of work is to be graded, that the concept of putting in effort for their own self-value is completely foreign. When I think back to my own struggles with writing as a student, I can't help but think that it's no wonder I couldn't write: there wasn't anything I knew well enough to write about with confidence. I'd love to see students given the opportunity to become experts at something, to the point where writing about it to share their knowledge and opinions would just be the natural step.

    61 votes
  8. Comment on What games have you been playing, and what's your opinion on them? in ~games

    scarecrw
    Link Parent
    I hope you enjoy it! It was one of my favorite game experiences. Something about the game made it much more natural to embrace the role-playing aspect of an RPG. I think it was mostly a nice...

    I hope you enjoy it! It was one of my favorite game experiences.

    Something about the game made it much more natural to embrace the role-playing aspect of an RPG. I think it was mostly a nice reprieve from all the games where you're "The Hero" who will inevitably be better and stronger and more special than everyone around you. Your character certainly grows and develops, but it stays much more down to earth and let's you be part of the world instead of treating it like a sandbox.

    I'll be curious if you have a take on the monastery quest. I can't say I enjoyed it, but I recall it was fairly devisive.

    4 votes
  9. Comment on What programming/technical projects have you been working on? in ~comp

    scarecrw
    Link Parent
    This is super cool! Do you have a link to any of the papers you used as reference? I'd love to learn about how this works.

    This is super cool! Do you have a link to any of the papers you used as reference? I'd love to learn about how this works.

  10. Comment on United States: What personal (non-business) tax software/program do you use? in ~finance

    scarecrw
    Link Parent
    The IRS system was available in my state last year, but it only covered federal taxes, not state. That meant I was going to have to use another service anyways to file state taxes, and it wasn't...

    The IRS system was available in my state last year, but it only covered federal taxes, not state. That meant I was going to have to use another service anyways to file state taxes, and it wasn't worth doing everything twice. I suppose if you're in a state without income tax then it might be worth it, but otherwise I didn't really see the benefit.

    5 votes
  11. Comment on Randomized trial shows AI tutoring effective in Nigeria in ~tech

    scarecrw
    Link
    I've been eagerly waiting to see how some of these AI-assisted educational programs perform, especially those focused on broadening access to education. A lot of the overly-rosy perspectives tend...

    I've been eagerly waiting to see how some of these AI-assisted educational programs perform, especially those focused on broadening access to education. A lot of the overly-rosy perspectives tend to compare outcomes to students who received no treatment whatsoever, which is a disingenuous way to report an approach's effectiveness, so it was very confidence inspiring to see that this also outperformed the majority of comparable interventions.

    I was also pleased to see from their videos how they seemed to have made the experience a social activity, involving interaction with the teacher and other students. A lot of failed attempts at using technology in education seem tailored for some mythical, emotionless, entirely self-motivated student.

    There's some draw to the idea that, if only the explanations were perfect and practice exercises just-so, every student would breeze through any topic. Maybe the AI optimists are correct, and we'll see some revolution coming, but from my experience with students in the present, a lot of the effectiveness of educational approaches stems from fostering an environment conducive for learning and building students' confidence in their own abilities. While current LLMs seem far from providing this on their own, I hope more efforts like this one find ways to use them in conjunction with more human approaches.

    7 votes
  12. Comment on Day 25: Code Chronicle in ~comp.advent_of_code

    scarecrw
    Link Parent
    Part 2 was definitely this year's "don't generalize, just inspect your input" problem. I can say that while I at some point knew how adders were set up, the only information that was necessary is...

    Part 2 was definitely this year's "don't generalize, just inspect your input" problem. I can say that while I at some point knew how adders were set up, the only information that was necessary is that each bit in the output is calculated in roughly the same way.

    minor spoiler

    For example, after sorting all the connections that led to a z output, I could see:

    ...
    gmw XOR cqn -> z08
    jgj XOR gff -> z09
    x10 AND y10 -> z10 // that's weird
    fgb XOR bmd -> z11
    qbw XOR gvj -> z12
    bgh XOR ctc -> z13
    pvs XOR wgc -> z14
    ...
    

    Just the obvious stand-outs accounted for 3/4 of the swaps for my input. Finding what to replace them with was a bit more challenging, but the same premise of "follow the pattern" still holds.

    Btw, thanks for sharing your Jai work! I'd never heard of the language, and while I'm not sure if I'm interested in trying it, I watched one of the creator's videos and the ideas seemed super interesting!

    1 vote
  13. Comment on Day 25: Code Chronicle in ~comp.advent_of_code

    scarecrw
    Link
    Short and sweet to finish! I just hardcoded all the dimensions, but it's the last day, so I'm happy enough with it. Smalltalk Solution Class { #name : 'Day25Solver', #superclass : 'AoCSolver',...

    Short and sweet to finish! I just hardcoded all the dimensions, but it's the last day, so I'm happy enough with it.

    Smalltalk Solution
    Class {
    	#name : 'Day25Solver',
    	#superclass : 'AoCSolver',
    	#instVars : [ 'locks', 'keys' ],
    	#category : 'AoCDay25',
    	#package : 'AoCDay25'
    }
    
    Day25Solver >> getHeights: aString [
       | heights |
       heights := OrderedCollection new: 5 withAll: 0.
       aString lines do: [ :row |
          row withIndexDo: [ :c :i |
             c = $# ifTrue: [ heights at: i put: (heights at: i) + 1 ] ] ].
       ^ heights
    ]
    
    Day25Solver >> parseRawData [
       locks := OrderedCollection new.
       keys := OrderedCollection new.
       (rawData splitOn: String cr , String cr) do: [ :schematic |
          (schematic startsWith: '#')
             ifTrue: [ locks add: (self getHeights: schematic) ]
             ifFalse: [ keys add: (self getHeights: schematic) ] ]
    ]
    
    Day25Solver >> solvePart1 [
    	^ locks collectAndSum: [ :lock | keys count: [ :key | (lock + key) max <= 7 ] ]
    ]
    

    I've certainly come a long with Pharo since the beginning of the month! I can't say I expect to use it much going forward, but I'm pleased to have gotten through AoC with it and definitely feel like I've gotten the "experience" of working in a language like this. I caught myself the other day writting in another language and thinking "oh man, I wish I could do it like Pharo..." which is always a great indicator that something's started to rub off.

    Always more puzzles to be had, but this year's AoC was a wonderful time!

    1 vote
  14. Comment on Day 24: Crossed Wires in ~comp.advent_of_code

    scarecrw
    Link
    This was a fantastic problem for using Pharo! I still don't have a generalized solution to Part 2, but this was a great opportunity to showcase the difference between Pharo and traditional...

    This was a fantastic problem for using Pharo! I still don't have a generalized solution to Part 2, but this was a great opportunity to showcase the difference between Pharo and traditional programming environments. Instead of writing an algorithm to solve, I focused on building objects and tools and just working in the inspector.

    I can't really share this process in a neat way, but here's a screenshot to give a sense of what this looks like during the process: https://i.imgur.com/3Sq9t8E.png

    Once I had a way to inspect the connections, swap outputs, and test the result, actually finding the solutions was fairly trivial: just look for the odd ones out that don't follow the pattern of every other connection.

    Pharo Smalltalk Solution

    1 vote
  15. Comment on Day 23: LAN Party in ~comp.advent_of_code

    scarecrw
    (edited )
    Link
    I'm sure at some point I knew some proper clique finding algorithm, but I couldn't remember anything. IIRC a generalized solution is NP-hard, but I took a look at the graph and noticed all the...

    I'm sure at some point I knew some proper clique finding algorithm, but I couldn't remember anything. IIRC a generalized solution is NP-hard, but I took a look at the graph and noticed all the nodes have the same degree, and just counted down from this upper bound on the clique size.

    Similar to yesterday, I think one of the most useful skills I've most developed for these types of problems is being able to quickly eyeball what approaches are going to fit the input size. I can definitely see myself in the past getting lost in the weeds on an approach that was never going to be efficient enough.

    I didn't do much refactoring, so code's pretty ugly today, with some goofy deep nesting.

    Pharo Smalltalk Solution
    Class {
    	#name : 'Day23Solver',
    	#superclass : 'AoCSolver',
    	#instVars : [ 'computers' ],
    	#category : 'AoCDay23',
    	#package : 'AoCDay23'
    }
    
    Day23Solver >> cliquesOfSize: size [
       | potentialCliques |
       potentialCliques := OrderedCollection new.
       computers keysAndValuesDo: [ :comp :neighbors |
          neighbors combinations: size - 1 atATimeDo: [ :comb |
             potentialCliques add: comb asOrderedCollection , { comp } ] ].
       ^ potentialCliques select: [ :x | self isClique: x ]
    ]
    
    Day23Solver >> isClique: aCollection [
       aCollection withIndexDo: [ :v :i |
          ((computers at: v) includesAll: (aCollection allButFirst: i)) ifFalse: [ ^ false ] ].
       ^ true
    ]
    
    Day23Solver >> parseRawData [
       | comps |
       computers := Dictionary new.
       rawData lines do: [ :line |
          comps := line splitOn: '-'.
          (computers at: comps first ifAbsentPut: OrderedCollection new) add: comps second.
          (computers at: comps second ifAbsentPut: OrderedCollection new) add: comps first ]
    ]
    
    Day23Solver >> solvePart1 [
       ^ ((self cliquesOfSize: 3) count: [ :clique | clique anySatisfy: [ :x | x first = $t ] ]) // 3
    ]
    
    Day23Solver >> solvePart2 [
       | maxSize cliques |
       maxSize := computers values first size + 1.
       maxSize to: 1 by: -1 do: [ :size |
          cliques := self cliquesOfSize: size.
          cliques ifNotEmpty: [ ^ ',' join: cliques first sorted ] ].
    ]
    

    Edit: simplified code a bit

    2 votes
  16. Comment on Day 22: Monkey Market in ~comp.advent_of_code

    scarecrw
    (edited )
    Link
    Not super proud of the result, but solving went smoothly. I didn't make any optimizations on the PRNG, though I suspect there may be some. My part 2 takes ~12 seconds to run, so if I have some...

    Not super proud of the result, but solving went smoothly. I didn't make any optimizations on the PRNG, though I suspect there may be some. My part 2 takes ~12 seconds to run, so if I have some time I might see if I can fix that. I think the issue is in storing and using the delta sequence as a key in the dictionary; that or in merging dictionaries.

    Pharo Smalltalk Solution:

    PRNG
    Class {
    	#name : 'Day22PRNG',
    	#superclass : 'Object',
    	#instVars : [ 'startingNumber', 'currentNumber', 'deltaHistory' ],
    	#category : 'AoCDay22',
    	#package : 'AoCDay22'
    }
    
    Day22PRNG >> initialize [
       startingNumber := 0.
       deltaHistory := 0
    ]
    
    Day22PRNG >> next [
       | oldPrice delta |
       oldPrice := self price.
       currentNumber := (currentNumber << 6 bitXor: currentNumber) % (1 << 24).
       currentNumber := (currentNumber >> 5 bitXor: currentNumber) % (1 << 24).
       currentNumber := (currentNumber << 11 bitXor: currentNumber) % (1 << 24).
       delta := self price - oldPrice.
       deltaHistory := (deltaHistory * 18 + delta + 9) % (18 ** 4).
       ^ currentNumber
    ]
    
    Day22PRNG >> price [
    	^ currentNumber rem: 10
    ]
    
    Day22PRNG >> startingNumber: anObject [
    	startingNumber := anObject.
    	currentNumber := anObject
    ]
    
    Solver
    Class {
    	#name : 'Day22Solver',
    	#superclass : 'AoCSolver',
    	#instVars : [ 'startingNumbers' ],
    	#category : 'AoCDay22',
    	#package : 'AoCDay22'
    }
    
    Day22Solver >> parseRawData [
    	startingNumbers := rawData lines collect: #asInteger
    ]
    
    Day22Solver >> solvePart1 [
       | prng |
       ^ startingNumbers collectAndSum: [ :startingNum |
            prng := Day22PRNG new startingNumber: startingNum.
            2000 timesRepeat: [ prng next ].
            prng currentNumber ]
    ]
    
    Day22Solver >> solvePart2 [
       | sums prng key totalSums |
       totalSums := Dictionary new.
       startingNumbers do: [ :startingNum |
          sums := Dictionary new.
          prng := Day22PRNG new startingNumber: startingNum.
          prng next; next; next; next.
    		1996 timesRepeat: [ 
    			key := prng deltaHistory.
             sums at: key put: (sums at: key ifAbsent: prng price).
             prng next ].
          sums keysAndValuesDo: [ :k :v | totalSums at: k update: [ :curr | curr + v ] initial: v ] ].
       ^ totalSums values max
    ]
    

    Edit: Sorted out the delta history hashing! Part 2 now runs in ~2.5 seconds which is good enough for me!

    1 vote
  17. Comment on Day 21: Keypad Conundrum in ~comp.advent_of_code

    scarecrw
    Link
    Definitely a step up in difficulty from the previous few days! I was shocked to almost make the leaderboard for part 1, but definitely struggled a bit more with part 2. I spent some time after...

    Definitely a step up in difficulty from the previous few days! I was shocked to almost make the leaderboard for part 1, but definitely struggled a bit more with part 2. I spent some time after refactoring to generalize the keypads a bit, though I still wouldn't describe today's solution as particularly comprehensible.

    Solution Logic

    The core insight was that, while each level was different, the best move sequence to get from one key to another was always the same for a given level. With 5 keys to move between and 25 levels, this leads to a manageable number of options to test.

    Pharo Smalltalk Solution

    1 vote
  18. Comment on Day 20: Race Condition in ~comp.advent_of_code

    scarecrw
    Link
    Came up with the approach I ended up using fairly quickly, but made some silly mistakes along the way. Part 2 still takes ~5 seconds to run, so I'm hoping to see someone else with a better...

    Came up with the approach I ended up using fairly quickly, but made some silly mistakes along the way. Part 2 still takes ~5 seconds to run, so I'm hoping to see someone else with a better solution.

    Smalltalk Solution
    Class {
    	#name : 'Day20Solver',
    	#superclass : 'AoCSolver',
    	#instVars : [ 'startPos', 'endPos', 'walls', 'goal', 'width', 'height', 'endDistance' ],
    	#category : 'AoCDay20',
    	#package : 'AoCDay20'
    }
    
    Day20Solver >> parseRawData [
    	height := rawData lines size.
    	width := (rawData lines at: 1) size.
    	walls := Set new.
    	rawData lines withIndexDo: [ :row :r |
    		row withIndexDo: [ :val :c |
    			val = $# ifTrue: [ walls add: r @ c ].
    			val = $S ifTrue: [ startPos := r @ c ].
    			val = $E ifTrue: [ endPos := r @ c ] ] ].
    	self buildEndDistance
    ]
    
    Day20Solver >> buildEndDistance [
    	| curr dist |
    	endDistance := Dictionary new.
    	curr := Set newFrom: { endPos }.
    	dist := 0.
    	[ curr isEmpty ] whileFalse: [
    		curr do: [ :pos | endDistance at: pos put: dist ].
    		dist := dist + 1.
    		curr := ((curr flatCollect: [ :pos | pos fourNeighbors ])
    			select: [ :pos | self canMove: pos ]) 
    			reject: [ :pos | endDistance includesKey: pos ] ]
    ]
    
    Day20Solver >> canMove: pos [
    	^ (pos between: 1 @ 1 and: height @ width) and: [ (walls includes: pos) not ]
    ]
    
    Day20Solver >> neighborsOf: aPoint distance: dist [
    	| neighbors |
    	neighbors := (aPoint x - dist to: aPoint x + dist) flatCollect: [ :r |
    		             (aPoint y - dist to: aPoint y + dist) collect: [ :c | r @ c ] ].
    	^ neighbors select: [ :pos | (self canMove: pos) and: [ (aPoint manhattanDistanceTo: pos) <= dist ] ]
    ]
    
    Day20Solver >> solveWithJumpSize: jumpSize [
    	| cheatValues jumpStarts |
    	jumpStarts := (1 to: height) flatCollect: [ :r | (1 to: width) collect: [ :c | r @ c ] ].
    	jumpStarts := jumpStarts select: [ :pos | self canMove: pos ].
    	cheatValues := jumpStarts flatCollect: [ :jumpStart |
    		               (self neighborsOf: jumpStart distance: jumpSize) collect: [ :jumpEnd |
    				               (endDistance at: jumpStart)
    				               - (endDistance at: jumpEnd)
    				               - (jumpStart manhattanDistanceTo: jumpEnd) ] ].
    	^ cheatValues count: [ :cheatVal | cheatVal >= goal ]
    ]
    
    Day20Solver >> solvePart1 [
    	^ self solveWithJumpSize: 2
    ]
    
    Day20Solver >> solvePart2 [
    	^ self solveWithJumpSize: 20
    ]
    
    4 votes
  19. Comment on Day 19: Linen Layout in ~comp.advent_of_code

    scarecrw
    (edited )
    Link
    Hard to complain, but this felt far easier than previous day 19s. I think I might just be biased having done enough coding puzzles in the past that I've probably done something similar a half...

    Hard to complain, but this felt far easier than previous day 19s. I think I might just be biased having done enough coding puzzles in the past that I've probably done something similar a half dozen times.

    Nothing special about the solution, just recursively solving each string by testing all the prefixes, caching results for part 2.

    Smalltalk Solution
    Class {
    	#name : 'Day19Solver',
    	#superclass : 'AoCSolver',
    	#instVars : [ 'patterns', 'designs', 'cache' ],
    	#category : 'AoCDay19',
    	#package : 'AoCDay19'
    }
    
    Day19Solver >> canBuild: design [ 
    	design ifEmpty: [ ^ true ].
    	^ (patterns select: [ :pattern | design beginsWith: pattern ])
    		  anySatisfy: [ :pattern | self canBuild: (design allButFirst: pattern size) ]
    ]
    
    Day19Solver >> countBuilds: aString [
    	| options ans |
    	(cache includesKey: aString) ifTrue: [ ^ cache at: aString ].
    	aString isEmpty ifTrue: [ ^ 1 ].
    	options := patterns select: [ :pattern | aString beginsWith: pattern ].
    	ans := (options collect: [ :option | self countBuilds: (design allButFirst: option size) ]) sumNumbers.
    	cache at: aString put: ans.
    	^ ans
    ]
    
    Day19Solver >> initialize [
    	cache := Dictionary new.
    ]
    
    Day19Solver >> parseRawData [
    	patterns := rawData lines first splitOn: ', '.
    	designs := rawData lines allButFirst: 2.
    ]
    
    Day19Solver >> solvePart1 [
    	^ designs count: [ :design | self canBuild: design ]
    ]
    
    Day19Solver >> solvePart2 [
    	^ (designs collect: [ :design | self countBuilds: design ]) sum
    ]
    
    2 votes