Log in

Applying A*

I've played a lot of freeciv and freecol over recent years. Both games let you order a unit to go to some square, and hopefully it takes the fastest route there. The 'world' is a square grid, of various terrain types and associated movement costs -- e.g. plains or desert take 1 move, but mountains take 3; roads and rivers take 1/3 no matter what terrain type they're laid over.

A* is this sweet magic algorithm for finding shortest paths in some graphs efficiently, vs. doing breadth-first search in all directions, but I was having trouble applying it mentally. I was using the common Manhattan distance heuristic, h((0,0),(x,y)) = x+y, and I wasn't getting good results: the algorithm would cheerfully march down a straight plains path to the goal, while ignoring a path that might step away and into mountains, but then ride a river to the goal much faster.

So I backed off, and thought about BFS. I realized that would work better if instead of naive BFS, enqueuing grid squares as you found them, instead you ranked them by total travel time so far. This is basically A* without a heuristic. Instead of exploring all paths N squares away, you'd explore all paths N moves away; it would still be radiating in all sorts of directions, but at least you'd find the shortest path to the goal.

Then I realized I'd been using the wrong heuristic; the right one should be the shortest possible journey. Or as WP says, "it never overestimates the actual cost to get to the nearest goal node." So the heuristic in this application has to consider rivers and roads, such that h() = (x+y)/3, not (x+y). This works much better: the plains march looks less attractive as it advances, converting cheap heuristic moves into actual plains moves, and the "mountain and away" move gets a chance to be considered.

Actually, units and roads can go diagonally, though rivers are rectilinear, so the proper heuristic is h((0,0),(x,y)) = max(x,y)/3.

Actually actually, infantry units only have one move, but are still guaranteed one square of movement per turn, so can march across mountains as easily as across plains; it's mounted units, with e.g. 4 move in freecol, that really care about base terrain type. Also fractional movement can be useful, e.g. I think a unit with 2/3 move left (after moving on river) can still move onto an adjacent plains.

See the comment count unavailable DW comments at http://mindstalk.dreamwidth.org/464671.html#comments

Headphones! 2

Ari, one of my hosts, said the other night that my (Panasonic) phones must be really good, that he'd been yelling at me from the kitchen and I didn't hear them. I don't know if he could have been yelling that loudly, but they certainly obscured something. And they're working pretty well now, there are Fanw and two kids six feet in front of me, and a bunch of gamers 10 feet away, but mostly I hear Christopher Franke.

If nothing's playing then there's some attenuation but not much blockage, not as much as earplugs, maybe. But with sounds, I mostly hear the sound.

Maybe I'm playing it too loudly. But that seems unlikely, I've never been a high volume guy. One of those people cursed with sensitivity to faint sounds, physical flinching from loud ones, but impairment in understanding speech...

See the comment count unavailable DW comments at http://mindstalk.dreamwidth.org/464425.html#comments

so many homophones

As I enter Japanese words, sometimes I mess up, or am guessing at what I hear in anime. I've noticed that almost anything I enter still has a meaning according to my tools. And words with the same pronunciation seem more common than in English.

As W reminded me, Japanese doesn't have that many syllables. There are about 50 basic syllables, maybe 80 including the compounds like 'gyo'. At 50, there are 2500 pairs, and 125,000 triplets. Even a large vocabulary can fill up most of that. By contrast, I read once that English has over 1000 syllables, which means 1 million pairs, and 1 billion triplets. Mind you, many of those won't be pronounceable, or valid under English phonotactics, or distinct[1]. But still, lots of words -- even 99% discounting would mean 10 million triplets.

See the comment count unavailable DW comments at http://mindstalk.dreamwidth.org/464294.html#comments



Have I talked about this before? Feels like I might have, but don't see anything in the past few months. I use earbuds a lot, to play music at home, or of course out and about. I've gone through a lot too, as they kept failing in one ear or the other, especially after being carried in my pocket for a while.

I remembered Panasonic as being a solid brand for electronics, looked up online and saw that they do make earphones -- though none sold in local stores -- and ordered three, figuring even Panasonic couldn't prevent thin wires from breaking. $10 each, supposedly good performance, certainly fine by me.

Aaaand I may have outsmarted myself, I'm still on the first set. Granted I was protecting it more, putting it in a ziploc bag before pocketing it, largely to reduce tanglement but presumably also reducing friction. But I lost the bag at some point, and it's still working.

I actually have five sets. One I'd bought earlier, the three Panasonics, and one we found on the floor of Grendel's one night and no one claimed. I also had 3 $1 sets I got from Dollar Tree, but they smelled so strongly once I opened the packets that I got paranoid about touching ultra-cheap Chinese products, and I think I threw them out.

Technically all the ones I have are in-ear, so they stay in better and there's more noise isolation, especially from the Panasonics.

See the comment count unavailable DW comments at http://mindstalk.dreamwidth.org/463893.html#comments

Really bad typo

Typos happen. Usually they don't change meaning too much. But I just caught one of my worst ever: I looked back at e-mail with W about meeting up for something, and where I meant "That works for me", I'd sent "That's work for me". I am mortified, and worried she's been feeling hurt the past couple days.

Re-reading is your friend. And your friends' friend.

See the comment count unavailable DW comments at http://mindstalk.dreamwidth.org/463788.html#comments


Notes to diary keepers

Date your entries. "When did I write this?" can be a fun detective exercise but not in the aggregate.

Fully date your entries. Yes, it's annoying to write the year all the time, but much later, when paging through (paper or textfile), you'll thank yourself for not having to find the beginning of year marker, assuming you left one.

If you have multiple diary books, putting the date range on the covers is nice too.


I found a book split between my USSR trip in 1991 and life notes in 2001-2002. Very frugal of me but makes the diary hard to order. Thanks, me.

A bunch of my diaries actually have class notes in the front, diaries in the back; school year ends without filling the notebook, so there was spare space...


On the electronic front, my journal files have a format of

{{2014 Dec 3}
life stuff

{special event like Arisia
whole bunch of lines

Not exactly sophisticated, but allows pretty free-form entry, while delimiting entries on characters you can %-bounce on in vi, while also not competing with the parentheses one might normally use (including smiley face parentheses, which don't close). And yes, I have a script somewhere that checks for mismatched curly braces. I designed the date header with some idea of easing parsing by simple scripts, though it hasn't come up much.

As you can see, the braces recurse, so I can group logically connected paragraphs within a day's entry.

One could obviously make the format smarter, with tags, or {{event} stuff}, but even what I have has been pretty helpful. I can find a day's entry quickly, beginning and end, and see the bounds of long sub-entries. There are ad hoc tags: "book:" at the beginning of a line for books I might want to read; "movie:" at the beginning for movies I've seen (yes, not very consistent); semi-regular tags for regular social events, to enable searching for those; "me on " for links to stuff I write elsewhere. Could be better though, like having an index at the top of such tags for standardized use.

In theory I could write a script to bound searches, e.g. looking for regexes within entries of a certain date, basically primitive database functionality. (Or you could put entries in a real database, but I'd rather stick to textfiles for stuff like this.) I haven't felt the compulsion to go beyond searching in less or vim, though.

See the comment count unavailable DW comments at http://mindstalk.dreamwidth.org/463533.html#comments


booyeah, I'm good!

So some months ago I worked on an AVL tree in pure C. My main goal was to get self-balancing happening at all, to demystify that process, and I did that; getting the code to be robust or even asymptotically appropriate (I'm still calculating heights every time I need to, not caching and updating them) was far down the priority list. So, while I tried to be correct in handling memory, it would not have surprised me if subtle bugs still existed.

My past work experience didn't emphasize use of static analysis tools. I think I played with lint a bit on my own, but relying on it or valgrind wasn't a thing. I finally investigated them today, ending up with cppcheck for source code check, and valgrind for what it does. And ran them on my directory of C/C++ exericses, which as small exercises, could easily have had lots of problems.

...not so much! cppcheck found a few problems, most notably a missing return value I wasn't testing properly in linked list, and a realloc bug[1] in my memoized Fibonacci table, and an unset ID variable in a threading program, but nothing else, including in the AVL tree or the new C++ hash table.

valgrind found some memory leaks in linked list and AVL tree... only because the testing main() for each was creating structures and then not freeing them before exit, because who cares at that point? With a manual destroy added, both check out clean. Which the list really should, it's pretty simple, but I'm stoked about the AVL tree doing so, since it's complex and memory correctness wasn't a top priority. Seems like I do have good habits.

There's also clang's static analyzer, supposedly deeper than cppcheck, though much slower to use. It's happy with my codes too.

Of course, valgrind can only test what's executed, so more use might uncover more bugs, but still, I feel good.

[1] ptr = realloc (ptr, ...) sets ptr to NULL if the realloc fails, which means a memory leak if nothing else is pointing to what ptr had been pointing to. Not having used realloc much, plus also not worrying about errors in a tiny program, this didn't stand out to me.

See the comment count unavailable DW comments at http://mindstalk.dreamwidth.org/463258.html#comments

inet_pton surprise

So, I've been working today on cloning my Ocaml chat program in C++. It's going slowly as I work on infrastructure, like exception-throwing wrappers to libc socket functions, and a RAII class for file descriptors.

In the process, I found something. I'd been using inet_pton() on the user provided server name, forgetting that I have to look it up first. I was getting away with it because testing has been local, client connect to localhost. My first code wasn't error checking inet_pton, but I got around to making the Inet_pton wrapper, which started throwing exceptions. inet_pton is supposed to return 1 on success (with the IP address written into a parameter), and 0 on invalid input. Turns out, given the string "localhost", it returns 0 but *also* writes in the local IP address.

That, or some weirder default was happening... yeah, on going the other way, I find the address (written or more likely just left over from the usual memset/bzero initialization) is which connects to localhost, just like the well-known Huh. Guess I should look up which looks messy an multi-purpose, but yeah, this seems one potential behavior of it, especially on a DHCP machine. OTOH, neither of the remote servers I have access to will connect to themselves via that address, so it's not reliable.

See the comment count unavailable DW comments at http://mindstalk.dreamwidth.org/463093.html#comments

Kate Elliott on writing women

9k word essay on writing women into fantasy "without quotas"; mostly it's a catalogue of the diverse role of women through history.


Some random notes I took:

1300s Lollards insisted on equality of men and women

Napoleon’s civil code restricted married women’s property rights, for

In tenth century Saxony there is “plenty of evidence that women
accumulated, transmitted and alienated predial estate"hi

In medieval Valldigna, Spain, Aixa Glavieta “went to court six times
until she forced the Negral family return to her the terrace with two
mulberry trees”

Zhou Daguan on Cambodia: "The local people who know how to trade are all
women. So when a Chinese goes to this country, the first thing he must
do is take in a woman, partly with a view to profiting from her trading

Anglo-Saxon Chronicles has king's sisters witnessing founding of a

A woman of high birth in any stratified society will have companions and
servants commensurate with her position. ..She will also usually retain
important ties to her birth family, and will be expected to look after
their interests.

In many cases the one person a lord, prince, king, or emperor could
absolutely trust was his mother: only she, besides himself, had full
investment in his success.

[Alexander] appointed [Ada] to the governership of Caria as a whole.
This woman was the wife of Hidrieus—and also his sister, a relationship
in accordance with Carian custom; Hidrieus on his death-bed had
bequeathed her his power, government by women having been a familiar
thing in Asia from the time of Semiramis onward.

See the comment count unavailable DW comments at http://mindstalk.dreamwidth.org/462819.html#comments

party food planning math

One last (probably) post inspired by Saturday.

A naive planner, trying to be considerate, might think "I'll have 40% vegan guests, 40% veg'n guests, and 20% omnivores, so I should have 40% vegan food... and 20% meat."

This is wrong! The vegans can only eat the vegan food, which will probably be poached by the other two groups. Put another way, if you locked the groups into only getting food from their own tables, then the omnivore table would likely *not* be 100% meat; even barbecues tend to have non-meat sides. 20% * (less than) 100% = less than 20%.

How *should* you distribute the food? I don't think there's a better answer than handwaving. But here's an illustrative model:

Imagine a vegan, two veg'ns who eat half-vegan and half-not food, and one omnivore who'll eat half meat, 1/4 vegan, and 1/4 veg'n. This implies that 9/16 of the food, should be vegan, 5/16 vegetarian, and 2/16 meat. One vegan, but more than half the food suitable for them -- again, because good vegan food will not be exclusive to them.

But of course it depends on your groups. If you know your veg'ns won't touch anything that's not dairy, and that your omnivores will only eat meat, then the naive approach is more valid. It can also apply to some main courses; if you're doing burgers in the first example, then 40% vegan, 40% veg'n-with-egg burgers, and 20% beef burgers, might make sense. Though there's still a chance of an omnivore trying the black bean or whatever burger out of curiosity, so poaching can still happen.

In my case, I traditionally have hummus and dates, and everyone eats those. I was hoping for 1/3 vegans at this party, and expecting 2/3 vegan or veg'n, and laid out entirely vegan food but for some camembert and some chicken. In retrospect I 'should' perhaps have gotten more cheese, to serve four people, though given actual attendance it worked out just fine.

I suppose that if you're planning a BBQ plus one vegan guest invited for socializing, it can make sense to just mark off some food as their territory while everyone else focuses on the pile of meats. Everything's situational; my main point is to caution against naive math.

See the comment count unavailable DW comments at http://mindstalk.dreamwidth.org/462346.html#comments


more on party costs

(I'm not trying to 'win' Iron Blogger, I'm just having lots of thoughts.)

I'm still bugged by the expenditures. You can live on like $5-6/day, surely I shouldn't be spending more than that per person for one meal? I spent $40 hoping for six people, that's nearly $7/person. In hindsight, given 4 people and what was consumed, I could have skipped the cashews, chips and salsa, less popular sausage, and one bag of pita, bringing cost down to $24, or $6/person, and we've probably have scoured everything clean except the chicken, due to lack of enough carnivores.

But, I guess it depends on what you get: eating frugally means stuff like pasta and rice and beans, or bread and peanut butter. Cheese, (good) crackers, and tomatoes are comparatively expensive: e.g. the crackers were about $5/lb. They're nutrient dense, being dry and fatty, but still twice the $/calorie of even overpriced whole wheat pasta. The tomatoes were $6, or $4/lb, which might be expensive even for tomatoes -- it's been a while since I bought any other kinds -- though as we ate nearly all, I have no regrets.

So basically, yes you can feed people cheaply if you prepare normal staple-based meals, but if you go for savory finger food, it'll be more expensive. Which is fine, it's just good to know and set my expectations accordingly. We probably still came in under restaurant cost, and finger food has advantages in prep (good for me as host) and not tying people to a table and large plate (good for guest circulation and freedom, though that's more relevant for larger parties.)

(Conversely it may be easier to overeat with finger food, if you just keep eating until it's gone or you feel dangerously stuffed.)

(I have a dim possible memory of realizing my old parties were more expensive than I expected, too.)

See the comment count unavailable DW comments at http://mindstalk.dreamwidth.org/462147.html#comments


holy crap auto is awesome

One thing easy to miss about Python is how it can easily print anything, including lists of dictionaries of lists of objects.  C++, not so much.  So I wrote a simple template function to print a vector of printable types, and then one for deques.

template<class T>
void pr_vector(const vector <T> &v) {
    for (auto i : v)
        cout << i;
    cout << "\n";
template<class T>
void pr_deque(const deque <T> &v) {
    for (auto i : v)
        cout << i;
    cout << "\n";

Well, lots of duplication there.  I tried templating on the container type too, template <class C, class T>, but the resulting C <T> didn't work; it probably should with some syntax, but I don't know what, yet.

But I figured I'd try auto:

void pr_cont(const auto &v) {
    for (auto i : v)
        cout << i;
    cout << "\n";

...that subsumes both templates.  And lots of others.  vector, deque, list...  Of course, the values themselves have to be printable, it can't handle a vector<pair<int, string>> because there's no printing on pairs.  But still, for C, this is amazing!

See the comment count unavailable DW comments at http://mindstalk.dreamwidth.org/462054.html#comments
At my last onsite interview I got asked -- out of curiosity, not as interview question -- what was so great about dynamically typed languages. I struggled to explain -- everyone knows why they're cool, right? Code is fast and compact to write! It is known!

But I've been thinking about the question some more. Right now I'm thinking there's one thing they're genuinely better at that doesn't come up that often; for the rest, it's more a historical accident of feature packaging, i.e. what else has traditionally come along with dynamic typing that made coding convenient.

The one thing: dealing with some variable length list of arbitrary values that you deal with at run time. Stuff like printf(), or message-passing into a closure-based object. I think I mentioned building a closure object in ocaml, and you can do it, but you need a sum type for various method inputs, and another for output, and it just seems like more work. Yeah, you get type safety for the work, but it's still more work. Likewise C has long had an ability to make things like printf(), but it feels clunky.

Also, based on language features, it seems likely that Lisp-style macros work better with dynamic typing, but I can't defend the claim. eval() seems to go with dynamic typing too, not that it's used that much IME.

The other stuff that's tended to come with dynamic typing:

* direct running of code, without a manual compile step. So faster development.
* (Lisp and Python, but not Perl or Ruby AFAIK): a REPL so you don't have to even write code into a file to run it, but can play at a prompt.
* easily making product types (tuples, lists of arbitrary types.) In C you have to declare and define a struct.
* garbage collection or at least reference counting, so little need to worry about memory management. Corollary: if you stick with small or at least short-lived "scripts", then resources like file descriptors or file handles don't have to be worried about much either; that's a domain thing rather than a language thing.
* And what might be the biggest one, a convenient environment:

In C you need to define a main function and include at least one header (like stdio.h) to do anything. Java's entry point is even more verbose. By contrast, a one line print statement is a valid scripting language or Lisp program. Put another way, in C++ terms, simply starting Perl gets you roughly the equivalent of

#include cstdio
#include string
#include regex
#include deque
#include unordered_map
#include unistd
#include sys/socket.h
#include cstdlib

...and probably more. (I left out the angle brackets because Dreamwidth is annoying.)

plus any statements are assumed to be contents of main() and thus executed. Python makes you import a few of the above as modules, though adds , bigints, and complex numbers.

Now, none of this depends on dynamic typing! ocaml and ghci provide REPLs and ocaml can directly run source files. Type inference and compact notation makes creating typed tuples on the fly trivial (on the fly coding, at least; not at runtime). Java's GC feels like half the reason programmers originally ooh-ed over it. And while Perl's default environment is unmatched AFAIK, having strings and some sort of container types and IO (more than C/C++) without import or use statements is common to Java and the ML-ish languages.

But if your experience of languages is something like C++, Java, and Perl/Python, as was not uncommon, then there's a clear bias in code convenience and compactness. And even with the ML-ish languages, with type inference and REPL, there's still nothing that matches Perl for simply doing useful system stuff right away without imports. I see no reason one couldn't exist, it just doesn't. So it's easy to associate dynamic typing with "lets me get stuff done quickly and concisely".

See the comment count unavailable DW comments at http://mindstalk.dreamwidth.org/461722.html#comments

mysteries of TCO

So I've learned that gcc/g++ do tail call optimization with the -O2 option; supposedly MS Visual Studio and clang do it when they can as well. I have tested this:

this got longCollapse )

See the comment count unavailable DW comments at http://mindstalk.dreamwidth.org/461499.html#comments

job update

Search continues. I'd expected to hear back from a couple places this past week, but did not. I'd been optimistic enough that I'd slowed down on applying. I've got a couple new interview processes starting Monday and Tuesday. I got a bunch of recruiter calls, including two within 30 minutes from different people named Brandon for local contract opportunities. I've also discovered multiple recruiters saying they'll e-mail me info after a phone call but not doing so. While I'm getting paranoid about mail from my linode server being received by others, I have no reason to believe I have any problem receiving mail myself.

If the current leads don't come through I'll probably transition to bumming on friends' couches, I'm pretty much at the final limit.

Studies and practice continue; I know a lot more than I did a year ago.

See the comment count unavailable DW comments at http://mindstalk.dreamwidth.org/461280.html#comments


party retrospective

Back in SF and Bloomington, I was decent at throwing game-and-talk parties, with a good layout of hors d'oeuvre. Here in Boston, I fell out. Partly because the direction of my social life didn't lead to making close friends in the way I was used to, partly because my stuff spread out so that I didn't feel happy about having people over much. A couple years ago I got my living room clear enough for short term house guests, and then to have W over for dinner and anime, but I still didn't try anything party like. More recently I turned my second bedroom back into such instead of a storage room, which came at the expense of my living room, such that I didn't even have W over this summer.

But there's this Iron Blogger thing, and our last two or three parties were at Sacco's Flatbread, which is loud, and eating out eats into our budget quickly. We were debating what to do for tonight's party, and I decided damn it, I was going to get things into shape, so we could save money and have a quiet environment.

And I did! Not even by punting stuff problems too much: some stuff went into empty boxes in a perfectly sensible way, though I do have one box newly labeled "junk to sort through later". I could have deployed all nine of my chairs in the living room, though as it happened I only needed four. At this point I could have house guests in *both* rooms.

Of course, if I don't get a local job soon, this will have been a last hurrah for the place, but still, cool.

It's also an object lesson in the negative value of having too much stuff; I'd have been happier with more parties or tete a'tetes and less stuff I barely touch.

As mentioned, I've got a distinct style; I've never cooked much for more than 2-3 people (including me.) Instead, lots of snacks, leaning toward the savory; any cooking is more like "boil dumplings" or "fry some sausage to cut up". It generally works well.

Tonight required some adaptation: I was hoping for two vegans (got one), two vegetarians (check), and one other omnivore (who forgot we were happening), so I aimed for a pretty vegan spread, plus one wedge of camembert, and some drumsticks I fried for the two meat eaters. Most of the food got eaten, which means I'm pretty stuffed -- probably bought too much for six people, and four people put a big dent in it, so... I dunno about the vegan sausages, that's not something I'm used to. I boiled one per the package, which led to it falling apart, but people ate almost all of it anyway; I microwaved the other, which mostly remained, though the vegan took the leftovers home. First choice would have been grilling, but my cast iron was busy with chicken, and I didn't feel like wrangling with my older pans.

Some years ago I'd discovered Mary's Gone Crackers for a party, as a wheat-free cracker for my wheat-free friend lyceum. They're actually really good in their own right, though pricey.

There's some selfishness mixed into my consideration: I aim for things that I'd be happy to have as leftovers. As a corollary I tend to be weak on drinks.

Introducing people to foods I've found is also fun. The 1.5 pound box of "Wild Wonders" tomatoes was almost completely finished. This is something Star Market has been carrying for a while: they're cherry-tomato sized (more or less) but heirloom in variety; the label just says "greenhouse grown cultivar tomatoes" but they're a lot tastier than a lot of greenhouse tomatoes are.

Setting up is pretty easy, at least when not doing a year's worth of de-cluttering in a couple hours. Afterwards... I could almost be tempted to use my dishwasher for the first time since the landlord installed it. Almost, but not quiet. Probably don't even have the right soap. And four people's worth of small plates isn't that much.

As for the party aims: success! We could all understand each other without fighting a loud restaurant's worth of noise. And I spent $40, which feels like a lot for 5 people (RSVPed) considering groceries) but probably still less than what four people would spend in a restaurant. Our budget was $60, so...

I dunno about vegan protein next time, if there is one. My first plan had been various flavored compressed tofus from Trader Joe's, which I know from experience are pretty tasty, but I balked at the price/lb. Though I guess they're about the same as the cashews. I guess at least one of the 'sausages' was mostly devoured, even if I feared otherwise.

We ate 90% of a 10 oz bag of pita. Yes, I weighed the remainder, and it's 1 oz. Also I cut the pita into 24 pieces and 2 are left. Though the other bag isn't quite 10oz, so the weights are a bit weird.

Oh right, one new thing! Usually I don't worry about healthy veggies for these things. Maybe baby carrots and cherry tomatoes, maybe occasionally a store tray of crudités. But this time I microwaved a pound of frozen broccoli, and added oil salt and pepper. I'm not going to try weight the wet remainder, but I'm sure we ate more than half. That's neat.

Tangentially, I don't know why both sets of parents I've seen close up try to get their kids to eat unadorned steamed broccoli to earn their desserts. It's much tastier with a bit of seasoning.

Tonight's crackers were TJ's Some Enchanted Cracker, tasty in its own right if totally different from Mary's Gone Crackers, and significantly cheaper. Also, totally consumed, along with the camembert.

The hummus isn't gone but greatly diminished (and it wasn't even the really good TJ hummus, which wasn't on the shelves); the chips vanished faster than the salsa. This is something I'd observed at ohanami parties: if I brought hummus it would get inhaled, while salsa would sit around, especially the hotter varieties. Some of the chips tonight were used for hummus, at least before that reminded me I'd been warming up pita wedges in the microwave but forgotten them.

Actually, yeah, I should make a distinct list of what hit and didn't:

+: pita and hummus (but maybe less pita... though if we'd had the fifth person we could have opened the second bag), runny cheese and good crackers, good cherry tomatoes, well-prepared broccoli, the dark vegan "Italian sausage" from TJ.
-: hot salsa, cashews (hard to judge, but I think I may have eaten most of what did get eaten, which wasn't a lot), the lighter colored sausage.

Plus there's various other things I could have tried. Dumplings, bread+oil, bread+butter, veggies and yogurt+dill dip (TJ European yogurt would work great for that), bread and salsa "bruschetta", frozen samosas (experimental), seasoned chickpeas (though not a finger food), chips and queso (not classy, but hey, not unpopular... dunno about this crowd, though), dates, or any other form of dessert.

I'd thought about just salt-and-peppered hard boiled eggs, but the TJ pre-boiled eggs felt too expensive, and I didn't want to peel a whole bunch myself, it's pretty hit or miss whether they peel easily.

One drawback of the evening: everyone coughed a lot when they came in, and I'd been coughing before then, though it faded. I suspect it was smoke from the fried chicken. But it wasn't that smoky: I really suspect cayenne powder on a high dry heat (I put some in the pan to get the underside of the chicken, but didn't bother adding oil.) Accidental chemical warfare...

See the comment count unavailable DW comments at http://mindstalk.dreamwidth.org/460922.html#comments


ocaml threads grrr

So for a coding test I had to make a chat client-server pair in ocaml. Done, based on a select loop. Well, mostly done, I didn't address blocking writes. I decided to redo the thing with threads, for the practice. Getting the basic functionality wasn't hard: synchronized queue for communication, simpler buffered socket readers than the first version had, and such.

Getting the threads to quit gracefully, though, that took a lot longer. I think part is due to ocaml's POSIX threads implentation: I'm told that "no one" uses it, they all use LWT (lightweight threads) instead. I can confirm some deficiencies: no Thread.detach functionality, for example, which was a big roadblock. And Thread.kill is in the API documentation, but when I tried to use it, got

Thread 2 killed on uncaught exception Invalid_argument("Thread.kill: not

Throwing an exception from the worker threads to notify the main program to join() them didn't work either, though I'm told I shouldn't expect that to work anyway. I think it works now, with a fair bit of polling -- not busy wait spinning, but reads timing out every 0.1 seconds to check for changes of state -- but that feels messy. As for whether it's simpler... well, it is fewer lines than the select() version, and should handle large (potentially blocking) messages better, so I guess so. Hmm, well, the core chat module is slightly shorter, but main is longer, and there's an extra SQueue module. Still, being more correct is good.

See the comment count unavailable DW comments at http://mindstalk.dreamwidth.org/460697.html#comments

Memory oddness

So we have these things called artificial neural networks, that learn in a supposedly neurologically-inspired manner. But AIUI, they typically take many repetitions to really learn something. Many many. And sometimes human learning seems like that, like rote memorization.

But other times, we learn with single-instance burn in. And not always because of some great emotional association, or repeated reflection. I had two instances of that yesterday.

First, I was up in Lowell for a job interview, and took the train. Now, I did that a few years ago, when a bunch of us went together to museums there. So as I emerged from the station this time, and looked across the street, suddenly I remembered exploring the park last time, before I'd gone to meet the others (who biked up). It's not like it's a particularly exciting or distinctive park, and I doubt I've thought of it since... but the impressions were there to be recalled.

As were the memories of being daunted and confued by crossing the nigh-freeway streets to get downtown, but that actually was mildly traumatic.

Second, I've been reading someone's Where I Read thread of the Robotech novels, based on the Robotech animated series, much of which I saw as a child. Last night the reader described a late scene where Minmei is seated outside somewhere, and her douchebag cousin-lover-manager Kyle is chugging a liquor bottle, before he finishes it and smashes it in mid air with a dropkick.

And I remember all that! Not well enough to guess who was on which side of the screen, but all of that suddenly seemed vividly familiar, in a way that other described scenes recently haven't. And unlike other remembered scenes -- the firing of the main gun, Roy dying, Max and Miriya fighting/courting, the SDF-1 punching a Zentraedi ship in Operation Daedalus -- I don't think I've thought about or reflected on this scene in the intervening nigh thirty years; it doesn't seem that iconic (though true, raging alcoholics are rare on Saturday morning cartoons, along with many other things distinctive about Robotech.) It's just some scene... that suddenly feels very fresh, after all this time.

I can't prove it's not some false memory constructed in response to the text. But I see no reason it has to be.

See the comment count unavailable DW comments at http://mindstalk.dreamwidth.org/460395.html#comments

C++ lambdas

I was catching up on C++11 last night. Learned about lambdas, and started playing around with them. A neat addition. But did they provide full closure capability, like creating a snapshot of state that the function can privately modify? Looked like no, and I was all set to be disappointed.

But at a job interview yesterday, I learned about the mutable keyword, which was described as letting you modify const things, like deep in a const object hierarchy. "Why would you even do that?" was my first reaction, though I can vaguely imagine why, "for the same reason that Haskell's purity annoyed me."

So I remembered that, and figured I would try adding mutable to the lambda. Ka-ching!

#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;

int main() {
    vector  v;
    for (int i=1; i<=10; i++) {
    int sum=0;
    for_each(begin(v), end(v), [sum](int n) mutable {sum+=n; cout << sum << endl;});
    cout << sum << endl;



Not that you need the external sum here, you could drop it and have [sum=0] for the lambda, but it illustrates the idea. Which isn't obscure, I saw it in the docs I was reading shortly after returning to them, but still, I found this on my own.

I've been applying to a bunch of C++ jobs more because of experience than because of any deep love for the language, but features like this and auto (type inference) and others from C++11/14 make it a lot more appealing.

See the comment count unavailable DW comments at http://mindstalk.dreamwidth.org/460210.html#comments

computer input stuff

My phone (Android 4, CM 11) swipe input is weird when it comes to profanity. So, there are three levels: its first guess for your word, two alternates to the side, and then a list you can bring up. 'suck', 'sucking', 'shit', and 'dick' will never appear in the first two levels, even if I go slowly and letter by letter -- 'shi' turns into 'shot', with 'shirt' and 'shoot' as alternates. Peter thinks it's a probability weight thing; I figure it's hardwired, with a short list of words being simply barred from your being able to input them too quickly (i.e. accidentally.)

But 'fuck', 'fucking', and 'fucker' I can enter quite easily. 'cunt' too. And 'pussy', with a bit of care (it's hard to swipe a double letter.)

Peter thinks it's also probabilities weighted by how you've used the phone, but I use 'suck' and 'sucking' in texts far more than any of the others... I've probably never tried to swipe 'cunt' before.

My thought for a while was that maybe fuck* weren't in the dictionary at all, until I added them, so wouldn't be barred, but I checked my personal word list and nope, they're not there.

So I dunno. Maybe it's more of an "accidentally unprofessional" filter, like words on the edge of acceptability are barred so you don't tell your boss how much something sucks, but the designers figured if you want to go full vulgar you knew what you were doing. Not how I'd do things.... and no, I don't see a profanity filter I might have turned off.

Wait, I'm wrong! I just checked again, and yes, Android Keyboard has a "block offensive words" option which is off, so I probably did that at some point... and I'm *still* not getting 'suck' or 'shit' as choices above the third level.


Totally unrelatedly, I finally have Japanese input working on my laptop! 日本語よ! I'd tried UIM a while back, per the Arch Linux default recommendation, but it didn't work. Then I tried SCIM a few days ago, and it seemed to not work either, but later I found myself typing in Japanese suddenly. Ctrl-Space turns it on, Ctrl-Shift cycles through modes (Anthy [Japanese], Unicode, English/European [which doesn't seem to do anything]. I should look into configuring that, because I need Ctrl-Shift-C and -V to copy and past from/to my Terminator terminal, so there's an annoying conflict there. Still, woo!

Is this more than a toy, given my weak Japanese skills? Slightly: online dictionaries tend to work best with Japanese input, not romaji, so now I can actually use them. And I've started studying it again, so that helps.

See the comment count unavailable DW comments at http://mindstalk.dreamwidth.org/460027.html#comments


Damien Sullivan

Latest Month

January 2017



RSS Atom
Powered by LiveJournal.com
Designed by Lilia Ahner