Showing posts with label programming. Show all posts
Showing posts with label programming. Show all posts

Friday, May 8, 2020

Things That are Getting Me Through

Everyone is experiencing these times differently. I'm fortunate enough to have a job that I can do remotely and to not be alone in my isolation. But here's some of what's been keeping me going, and I hope it can help.

Pets

I have a cat. I feed her every day. She sits on my lap and purrs and bites me.

We also caught a sourdough starter. I feed it every day. It has not yet bitten me.

Self Care

Because I now live what my father has generously called "the life of a scholar", I don't get a lot of sunlight. I find that vitamin D supplements help me sleep better.

I was never a gym person, but the total lack of activity has started to wear on me. I've taken up the seven-minute workout, which I like much better than I thought I would.

The first few weeks without shaving are all terrible scraggly neck beard for me. With nobody to see it, what better time to push through that period and find out what other terrible scraggly facial hair I can grow?

I miss math and I also miss programming. I've taken the opportunity to write a couple of janky scripts: one that generates thumbnails for video files, and one that removes cruft from CBZ and CBR files, shrinks them a little, and converts CBR to CBZ. Use at your own risk, but I am proud of them.

I brûléed a Cadbury creme egg. It's worth doing at least once.

Media

Before this, we sometimes saw a comedy show called Spoons & Toons & Booze. They've become Spoons & Toons & Booze & Zoom now, and they're raising money for the employees of the theaters where they used to perform.

On a smaller scale, we've hosted a few movie nights with distant friends on twoseven.xyz. It works about as well as any new tool, which is to say, plan at least an extra half-hour at the beginning for socializing and troubleshooting. Test what you're planning to do by yourself first.

On Netflix, after The Great British Bake-Off, Terrace House might be the most bizarre and calming show I've found. Six young Japanese adults live in a nice house and get nice cars. There don't seem to be any stakes or anything? They all keep going to their normal jobs and stuff. After each episode, a bunch of enthusiastic commentators remark on all the drama that may or may not have happened. It's pretty good.

Sylvan Esso released a new live album.

Podcasts

Lots of podcasts will keep you informed or expose you to new and complicated ideas. These are (mostly) not those.

Phoebe Reads a Mystery

Phoebe Judge, host of Criminal, reads a mystery novel one chapter at a time. She started with The Mysterious Affair at Styles, then The Hound of the Baskervilles, and currently The Moonstone.

St Elwick's Neighbourhood Association Newsletter Podcast

Recently launched by Mike Wozniak, frequent guest on The Beef and Dairy Network. The usual arc of an episode is roughly: bizarre to sad to cringe to absurd. It's pivoted into the current situation seamlessly by releasing shorter, more frequent episodes, and I think they're stronger for it.

The Tranquillusionist

Helen Zaltzman of The Allusionist (same feed) reads odd things in a calm voice, with musical accompaniment by her husband, Martin Austwick.

Make My Day

Josh Gondelman has a single guest on to play a made-up game show, where points are given to answers based on how much they cheer him up. Money is given to charity. Strange motivational speeches are delivered.

Seltzer Death Match

Self-explanatory, I think. They've been editing through a backlog recently, so there's a bunch of new ones.

372 Pages We'll Never Get Back

Two of the minds behind RiffTrax read through bad books. My cousin recommended this to me and in exchange I recommended

Bad Books for Bad People

Jack Shear and Tenebrous Kate read through books that they think the other will enjoy/hate.

Monster Man

James Holloway reads through old monster manuals, a couple entries at a time. I particularly enjoyed the episode about mind flayers, and why they are the perfect 70's Doctor Who villain. Nominally topical!

Others

Life is short. Also have these recommendations, with the understanding that I don't enjoy them any less for having lost the energy to describe them:

Games

When there was less on our minds, my wife and I would set aside days to solve mysteries, things like Sherlock Holmes Consulting Detective or T.I.M.E. Stories. These days we play a lot of LEGO Batman 3, which is good because neither of us is any good at video games and it's fun regardless.

Quarantine has also gone on long enough that I found my old RuneScape account. While my old character is still sitting there in RS3, I've been playing Old School RuneScape, and it's really interesting to start again at the beginning.

I've started playing in a Lasers & Feelings game with a bunch of doctors and it's good fun and breezy. The same group is also getting ready for a more involved 5e game which should be interesting.

I've been playing in a West End Games/d6 Star Wars game and it's wild. The rules can be found online practically by accident, and they're worth a look.

Finally, it looks like I will be GMing again, likely 5e. I've never actually run 5e proper, but I'm hoping I pick it up easily enough.

Tuesday, March 24, 2020

7d6, split between two attributes

On 20 Feb 2020, PlanetNiles (Ey/Em) NB on the workshop channel of the OSR Discord asked1:

7d6, split between two attributes

What values are even possible?

One way to think about this is not in terms of the values themselves, but in terms of the difference between the two paired attributes. The maximum difference is when all dice are allocated to one attribute, leaving the other empty. This is then equivalent to the sum of the dice.

The minimum difference between the two is a form of the well-studied partition problem: given a set of numbers, can it be split into two sub-sets with equal sums? A heuristic method that can usually2 find the smallest difference between our two subsets (and therefore if they can be equal or not) is called the Karmarkar-Karp method, which works as follows:

  1. Take the two largest numbers in the set. Assume that these will go in opposite partitions.
  2. Because they will go in opposite partitions, we subtract them from each other.
  3. Instead of now deciding which partitions they will go in, we return the difference between them to the set. This is effectively deferring that decision until later.
  4. Repeat steps 1-3 until there are only two numbers left. The difference of these last two numbers is the smallest difference we can make with this set.
Note that we didn't actually find what the partitions are, only what the difference between them is here. I hope this is clear enough, but I'm also sure that clearer explanations can be found with minimal searching.

With some wrangling, we can produce this lovely chart, where a heavier hexagon is a more likely pairing.


Hexagons are elegant, as odd/even combinations that cannot occur are skipped naturally.

From this, it looks like the system gives a lot of flexibility in assigning scores to your attributes.

What Values are Likely?

I have a concern about this mechanic though: if you give someone a range of numbers, and tell them to pick one, they will tend to pick in the middle3. If a player is dead-set on being boring, how boring can they be?

It might not be exactly true, but we can show the distribution of all the high stats and all the low stats together, and then compare them to the distribution of 7d6 literally divided in half (which is approximately normal).

This doesn't look great, but PlanetNiles has actually already got us covered here:

Of course. I'd further consider including subsystems where the difference between attributes had some sort of effect. So favouring one over the other would prove beneficial in some way, or at least open up different options.
The strength of this mechanic then will rely on the strength of the system. Given the range of the first figure though, I have confidence that an interesting system could be built here.

What about other mechanics?

Suppose we were looking for a similar mechanic, except that it would force a difference between the attributes where possible. We might expect intuitively, that fewer dice and larger dice are harder to partition effectively. This table gives the probability of a forced difference (although does not consider the size of that difference).

From this table, I thought I would look at 3d20, because it forces a difference the most often. The figures below have the same interpretations as the similar ones above, but for 3d20 instead of 7d6.

Python

This was my first project using Python, and I think it's an all right language. It'll probably displace Octave in my repertoire, but I'm sure I'll be right back at Perl if I start doing string stuff again. The code's a bit janky, but you can take a look here.


1 “Asked” a little more directly this time, if only because I asked first.back

2 According to Wikipedia, this method is “bad for instances where the numbers are exponential in the size of the set,” so like, probably fine?back

3 I only know this anecdotally: if you tell a plant operator to keep some process temperature between a high limit and a low limit, without fail they will control it to the middle of the two. It makes sense to a person, but the optimal temperature is provably at one of the two extremes. Possibly, this is an extension of the anchoring effect.back

Tuesday, April 9, 2019

Mad With Power in the Gardens of Ynn

The Gardens of Ynn is one of the most immediately exciting RPG books that I've read in a long time. In general, Cavegirl is a brilliant and exciting writer, and you can give her money if you'd like to support her work (outside of buying her other things, which are also brilliant). But man, that book could really use an editor, and the PDF has some weirdness. Now that I've been playing with Ghostscript, I thought I'd try my hand at solving one of the more egregious problems (IMO).

Problem

The layout of Ynn is roughly like this: there's a handful of tables in the beginning of the book, and to generate locations you roll on them. Each of the results on those tables is expanded upon, usually at about a page-length, later in the book. But the real problem is flipping around the book: the tables don't have page numbers, nor are they cross-referenced. Changing the text of the book or adding cross references are possibly too advanced at the moment, but I can add a table of contents, and hopefully this will make the PDF more useful at the table.

Solution

I copied-and-pasted the table of contents in Ynn, and lightly edited it (for example, "Chronological Abberations" is now "Shepherd of the Trees"). Then I went through and converted it to pdfmark format. This process was unfortunately not very automated, excepting some find-and-replace tools. Finally, I ran a command that looks like:

$ gs -o Ynn.ann.pdf -sDEVICE=pdfwrite -dPDFSETTINGS=/prepress Ynn.pdf Ynn.toc.pdfmark

Results

Now I get this nice sidebar on my PDF and I'm happy:

As a detail-oriented person, there are still lots of things in the book that bother me a little. But it's much more usable now.

Sunday, April 7, 2019

Hapaxes in Context

My last post about Hapaxes in the Ultraviolet Grasslands was well received, even though I was not satisfied with the strength of its conclusions. Here, I attempt to add context to the hapaxes through the use of some inadvisable perl scripts.

Process

Again, I'll assume some familiarity with bash. I'm also using a pair of perl scripts I wrote which probably don't generalize well, but which were fit for purpose. If I'd planned ahead, I'd have written them both as one script.

First, we'll do some very similar things to what we did last time:

$ python3-pdf2txt.py -o UVG.txt UVG.pdf
$ cat UVG.txt |
tr A-Z a-z |
sed -E "s/\s+|['‘’]s\s+|[–—-]+/\n/g" |
sed -E 's/[][<>.,();:+?!%/©&“”"#*]//g' |
sed -e "s/^['’‘]//g" |
sed -e "s/['’‘]$//g" |
grep -Ev "^[0-9d]+$" |
sort | uniq -u > UVG.hapax
$ /bin/diff -i /usr/share/dict/words UVG.hapax |
grep ">" |
cut -d " " -f2 > UVG.hapax.new

As before, linebreaks have been added for clarity, but you'll have to escape them to use this code directly. Also note that this time we remove the possessive "s" from the ends of strings, and we split on hyphens as well as spaces.

Next, we go back to the PDF, but we extract it as XML to access the character position data:

$ python3-pdf2txt.py -t xml -o UVG.xml UVG.pdf
$ cat UVG.xml | ./xml2tsv.pl > UVG.tsv
$ cat UVG.hapax.new | ./pdfmarker.pl UVG.tsv > UVG.pdfmark

The scripts I mentioned earlier are xml2tsv.pl and pdfmarker.pl. The former (very naively) strips extraneous markup, leaving each line with a character, four coordinates, and a page number. The latter reads that tsv file (given as an argument) and locates the coordinates of each word piped to it. (As each word only appears once, this is straightforward.) It outputs these coordinates in pdfmark format, a way to annotate PDFs.

Finally, we merge the annotations back into the original PDF as highlights:

$ gs -o UVG.ann.pdf -sDEVICE=pdfwrite -dPDFSETTINGS=/prepress UVG.pdf UVG.pdfmark

Results

This method is much pickier, in part because of the difficulty of parsing a PDF consistently. From the text file, we extracted 164 words of interest, but there are only 139 annotations in the final count. I expect that the difference is words that are represented differently between the txt and xml formats. For example, if the space between two words isn't represented by a whitespace character in the xml, it does not detect as a word boundary when we look for it. But the heuristics that build the text output may still correctly "add" the space back in. This method also considers each half of a hyphenated word separately, so they are more likely to appear multiple times or to be in the dictionary.

These numbers are smaller than before for a different reason also: I have been using the free sample version, so that I can share the results. This is 78 pages, down from 158 pages in the backer version I was using before. So while we can still get a list of the output as before:

rewatch
pusca
eskatin
ashwhite
demiwarlock
vidy
engobes
tollmistress
dejus
orangeware

We can also then go find where these words are highlighted in the PDF:

In the highlighted PDF, it's easier to see that the majority of the hapaxes are proper names and normal words that my dictionary doesn't contain, like "lunchbox" and "calcinous". There are still lots of gems though, like a sign that reads No Lones to Adventerers, Frybooters or Wagonbonds, the goddess Hazmaat, and zombastodon lair. You can take a look here:

Disclaimer & Plug

I still back Luka on Patreon, and I have backed his Kickstarter as well. The Kickstarter campaign is now in its final week, and I'm very excited for it.

The free version of the PDF (available unannotated in the Kickstarter description), is licensed under a CC By-NC-ND 4.0 license. Arguably, because all the changes I have made to it were procedural, maybe this still complies with the "NoDerivatives" part of that. But I don't actually know, so I went ahead and asked Luka and he said this was ok anyway.

Tuesday, March 19, 2019

Hapaxes in the Ultraviolet Grasslands

At the beginning of the glossary of the Ultraviolet Grasslands (UVG), Luka asks: What have I missed? What needs more details? One way to find things that might be missing is to look for hapaxes in the work. This is not a good plan, but I tried anyway.

Process

The following stuff was done in bash. I assume some familiarity with the commands, but comment on particular decisions that I made. It could be cleaned up.

First, we need the corpus as text so that we can work with it:

> python3-pdf2txt.py -o UVG.txt UVG.pdf

Then we clean up the text, and select all the words that only appear once:

> cat UVG.txt |
tr A-Z a-z |
sed -e 's/\s/\n/g' |
sed -E 's/[][<>.,();:+?!%/©&]//g' |
sed -e "s/[‘’]/'/g" |
sed -e 's/[“”"]//g' |
sed -e 's/[–—]/-/g' |
sed -e 's/[-"'\'']$//g' |
sed -e 's/^[-"'\'']//g' |
grep -Ev "^[-0-9'd]+$" |
sort | uniq -u > UVG.hapax

Line breaks have been added for clarity. Parts of this bear closer examination:

sed -e 's/[“”"]//g' |

This could be folded into the second sed statement, but it might be useful to keep but normalize double quotes for some purposes.

sed -e 's/[-"'\'']$//g' |
sed -e 's/^[-"'\'']//g' |

Quotes and hyphens at the beginning or end of a word are unlikely to carry much information, so they are stripped. This must happen after all the dash and quote characters have been "normalized".

Lots of the words that only appear once (6832 now) are not exciting. So we'll remove all the dictionary words:

> /bin/diff -i /usr/share/dict/words UVG.hapax |
grep ">" |
cut -d " " -f2 > UVG.hapax.new

Again, line breaks have been added for clarity. The full path to diff is specified because I've otherwise aliased diff to colordiff.

Results

Of the 1612 hapaxes now left, it might be interesting to see how the characters are distributed.

> cat UVG.hapax.new | fold -c1 | sort | uniq -c | sort -gr

This gives a table of character frequency:

3223
1647e
1295a
1155i
1106o
1097r
1016s
1010n
916t
877l
837-
. . .
   43
3 
38
2ô
2ç
29
27
1Ö
1ñ
1ë
1â

The most common "character" is blank, and I suspect this is related to newlines (3223=2*1612-1). The other "blank" character appears to be a space that did not get stripped out initially, or which was later re-introduced. Perhaps it is some kind of other whitespace.

The most exciting thing in this table (I think) is the high occurrence of the hyphen. This means that roughly half of the "hapaxes" are likely composite words, and worth considering separately. For example:

sub-node
six-lives
noble-pillared
mercy-is-weakness
marrow-beet
curse-maddened
six-limbed
force-glass
stock-piled
self-regenerating

Disregarding hyphens, these are all words a dictionary knows, but which Luka may be using in novel ways.

The remaining (unhyphenated) words, are a mixed bag. Take this random sampling:

pyrokinetic
skalin
psionics
dustland
irshe
replicator
10x
visec
mearls
mirodar

Many of these just show the limitations of my dictionary ("pyrokinetic", "replicator"). Some of them show the limitations of the process ("10x", "jrientsblogspotcom"). Some are ad-hoc compound words ("dustland", "malicereflective"). The rest are either made-up, proper nouns, or typos, and I don't have a way to distinguish between them. It's possible that some of these were "created" by pdf2txt, which uses tunable heuristics to decide where to draw word boundaries.

If you're interested in playing with the lists, I've uploaded them here. They are split into "hyphen" and "nohyphen", and should be alphabetical.

Disclaimer & Plug

I back Luka on Patreon at the $1/mo level, which grants me access to early drafts of his projects. The version used for this project was the most recent version available to backers, but it has not been edited.

UVG is currently running a Kickstarter for a fancy printed version with editing and more art. There's a link to a free version of the manuscript there too.