aebletrae [she/her]
- The ordering of each row should not matter.
This is true for your abstracted rows, but is maintaining eight sets of three square states, two or three of which must be updated with every move, really a better model than a single sequence of nine, where only one needs to change at a time? It’s more complex to think about, and is less efficient to update. When you throw in steps to canonicalize the rotation and reflection, which may produce different transformations from the input/output grid on the first three moves, you may need to change even more set items with each move.
It’s true that, mathematically, the mapping from grid to sequence is arbitrary and the only thing that matters is consistency, but if you view programming languages as a way to communicate with humans, then clarity of purpose, rather than mathematical idealism, should be your goal. Use a nine-item array or a three-by-three nested array for the underlying storage and treat your eight win-checking sets as views into that more ordered structure. These views could well be functions that return a set and are themselves held in a set to be applied in any order. Similarly, treat canonicalization as another way to view the underlying board.
You could sidestep the mutable borrowing by not mutating individual squares. Take a leaf from the functional-programming books and use a function that takes a board and a move and returns an entirely new board. Or takes a board and returns one of the abstracted row sets. There are only nine squares and nine moves. The win-checking views aren’t needed before move six. A bit of copying isn’t going be a problem.
Having thought about this some more with practicality and clarity thrown out the window in favour of abstractions, how about this?
A game is a sequence of moves. Past moves are immutable, future moves unknowable; a singly linked list fits the bill here.
Each move consists of a player token and a position. The position might ordinarily be thought of as a grid index but, as you point out, it could just as well be membership in one of the potentially winning lines. Either a move is part of one of these lines or it isn’t. This makes the position equivalent to a bit field. If each potential win line is distinct, they could indeed be held sparsely in a set.
Checking for a win then consists of counting player tokens for each potential win line and checking for crossing the necessary threshold. Filter, sum, max, greater than?, any?
I think this scheme would be applicable to arbitrary game boards, with none of it requiring mutation. Is that the kind of thing you were after? The reflection/rotation equivalence isn’t present here, but I still think that’s more an artefact of analysis, rather than a property of gameplay.
Ah, Enhanced, the folks that brought us interrogation.
Are other lines in .profile
being executed, or is the whole file ignored? Have you logged out and in again since adding these lines?
You haven’t said what experience you have so far, so this is kind of a generic answer, but:—
Step 1: Write. Stop worrying and just write things down. Doesn’t matter how disorganised it is, start writing. The point here is to avoid paralysis by analysis. It’s all too easy to focus on doing things right or using the perfect system, and not actually get on with the real objective. Reviewing and reorganisation are good actually, so you shouldn’t worry that this is a messy way to start. It’s an immediate start.
Step 2: Divide and tag. Go back over what you have and identify its parts, placing them into separate notes. Some will be quite separate, self-contained ideas, like short quotations, while others will be connections between ideas. Add labels, like hashtags or Wikipedia categories, to these parts and connections. At first, think of a couple of generic labels (“#Liberalism”, “#France”) and one or two more specific ones (#HarpersFerry, #AliensAct1905). The best kinds of labels will depend on your specific research, and you’ll figure them out as you go along. They’re easy to add and/or modify, so they don’t have to be perfect from the get-go.
Step 3: Synthesise. As you record and tag more notes, the shape of your information will become more apparent, and a tool like Obsidian can be used to view the connections between your ideas. Perhaps more importantly, it can also show you the more orphaned ideas that need fleshing out if they are to be brought into a broader synthesis, or left out as part of a different topic.
Zettelkasten-type systems work better as you add to them, so they can seem a bit pointless or confusing at first. Imagine how useless a three-page Wikipedia would be. This is why it’s so important not to get bogged down with details of workflow before you even start. Get going by recording the things you find and what you think about them, in whatever way you can now, label them in whatever way makes sense now, and then examine the shape of the connections to guide you through refinement. No one gets to the top of a mountain in one leap, but the view does improve with every step upwards.
But those kinds of initialisations belong in .profile
(or, if you’re using a weird desktop environment, its own configuration file), particularly if you want .desktop
files to work. (In .bashrc
, PATH
will grow longer in each subshell, which shouldn’t cause problems but is wasteful.)
So, what desktop environment (GNOME, KDE, Cinnamon, etc.) are you using?
.profile
is executed by login shells for the benefit of it and its subshells, and by DEs like Cinnamon for the benefit of .desktop
launchers at login.
So, have you logged out and back in again since adding these lines to .profile
?
And of course, the .profile
has to be executed properly for its configuration to take effect, so it`s useful to know if the problem is with those specific lines, or the file as a whole.
Add:—
date >> ~/profile-execution-log-top.txt
echo $PATH >> ~/profile-execution-log-top.txt
to the top of .profile
, and:—
date >> ~/profile-execution-log-end.txt
echo $PATH >> ~/profile-execution-log-end.txt
to the bottom of .profile
(use alternative paths as you see fit) to monitor that activity. You can test this by sourcing .profile
but the real test is logging out and in again. Look at the time when you do this so you can correlate each action with each timestamp in the log files. If .profile
is executed to completion, you should have two files with matching timestamps but different PATH
s. If you don’t have a matching timestamp in the “end” log file, there’s a problem mid-execution. If neither file is being updated, .profile
isn’t being executed at all.
If wealth were actually distributed in the US equally that might be true, but as it is it’s more than double what most Americans have, even ignoring inflation.
The average net worth of all American families was $746,820, according to the Federal Reserve’s 2019 Survey of Consumer Finances, while the median figure was $121,760.
— The Average Net Worth Of Americans—By Age, Education And Ethnicity