Live data from Hacker News

Arthur Whitney's one liner sudoku solver (2011)

dfns.dyalog.com

201–210 of 210 posts

Re: Arthur Whitney's one liner sudoku solver (2011)

#201
post #199

Earlier quoted context omitted.

All programmers think they have culture and values. Getting them to agree on what those are and to prioritize them the same is the hard part. Having an open mind is great, and if you’d said that from the start I totally would have agreed, but you didn’t, you dismissed the GP’s comment with relatively strong language as being very wrong headed on behalf of the entire community, and doubled down on that stance in your…

First off, thanks for continuing this exchange with me. Text communication between strangers is fraught with miscommunication perils left and right, so hanging in there is a really nice gesture. Cheers. It's so weird, though. Everything disagreeable you point out with my comments, I kind of feel like is true of GP's comment. It casually dismisses the content of OP, injecting a strawman about a "metrics". Wore still,…

I appreciate that your tone is softening with me, and that you took the time to mention some positives. De-escalating from a potential misunderstanding is the right way to go.

I’ve reread your comments, and they still read like an attack to me, while the top comment does not. You may feel like you’ve drawn a line, but the implications you made were quite clear. Calling it a dick move is a more direct attack, and talking about how it offends you tends to demonstrate that you have been and still are in fact attacking. Using strong language in a direct reply and talking about how wrong the mentality is is always going to be taken as an attack on the comment you’re replying to.

Personally I feel like the “one line” part of the article title is intentionally provocative, and as such, it invites critique, which is what the top comment is. It’s both impressive to fit a sudoku solver on one (short) line, and also at the same time, making a claim that can’t be fairly compared to other languages. As such, it is fair to point out that there’s a more universal way to evaluate the size of Arthur Whitney’s solution that is more compatible with other languages, and combined with the fact that everyone (including you?) already agrees that lines of code aren’t a good metric for anything, it’s not clear why you’ve taken such issue with that casual comment.

The article, disappointingly, doesn’t explain Whitney’s solution in words that non K readers can understand. At a glance, I would assume it’s a more or less brute force search over all possible sudoku boards and then matching against the cells, rows, and columns rules. In a way then, Whitney’s solver might be seen as a succinct statement of the rules of sudoku, which are indeed relatively short in any language.

Re: Arthur Whitney's one liner sudoku solver (2011)

#203

Earlier quoted context omitted.

Do you have examples of primitives that are hard to replicate? I can't think of many off the top of my head. > tables and IPC Sure, kdb doesn't really have an equal, though it is very niche. But for IPC I disagree. The facilities in k/q are neat and simple in terms of setup, but it doesn't have anything better than what you can do with cloudpickle, and the lack of custom types makes effective, larger-scale IPC diffic…

None of the primitives are necessarily too complicated, but off the top of my head things like /: \: (encode, decode), all the forms of @ \ / . etc, don't have directly equivalent numpy functions. Of course you could reimplement the entire language, but that's a bit too much work. Tables aren't niche, they're very useful! I looked at cloudpickle, and it seems to only do serialisation, I assume you'd need something el…

> None of the primitives are necessarily too complicated, but off the top of my head things like /: \: (encode, decode), all the forms of @ \ / . etc, don't have directly equivalent numpy functions. Of course you could reimplement the entire language, but that's a bit too much work.

@ and . can be done in numpy through ufunc. Once you turn your unary or binary function into a ufunc using food = np.frompyfunc, you then have foo.at(a, np.s_[fancy_idxs], (b?)) which is equivalent to @[a, fancy_idxs, f, b?]. The other ones are, like, 2 or 3 lines of code to implement, and you only ever have to do it once.

vs and sv are just pickling and unpickling.

> Tables aren't niche,

Yes, sorry, I meant that tables are only clearly superior in the q ecosystem in niche situations.

> I looked at cloudpickle, and it seems to only do serialisation, I assume you'd need something else to do IPC too? The benefit of k's IPC is it's pretty seamless.

Python already does IPC nicely through the `multiprocess` and `socket` modules of the standard library. The IPC itself is very nice in most usecases if you use something like multiprocessing.Queue. The thing that's less seamless is that the default pickling operation has some corner cases, which cloudpickle covers.

> Im not sure what you mean by inefficient hacks, generally you wouldn't try to construct some complicated ADT in k anyway, and if you need to you can still directly pass a dictionary or list or whatever your underlying representation is.

It's a lot nicer and more efficient to just pass around typed objects than dictionaries. Being able to have typed objects whose types allow for method resolution and generics makes a lot of code so much simpler in Python. This in turns allows a lot of libraries and tricks to work seamlessly in Python and not in q. A proper type system and colocation of code with data makes it a lot easier to deal with unknown objects - you don't need nested external descriptors to tag your nested dictionary and tell you what it is.

Re: Arthur Whitney's one liner sudoku solver (2011)

#204
post #21

I'll sometimes gauge code complexity by comparing the number of lines of code against the output of tar -cf - . | gzip | base64 | wc -l IE "how much does it compress?" Looking at APL -- I'm reminded of what happens if I accidentally send the gzipped output to my tty... I'm impressed that there's anyone who can follow along (can you find the bug?) to code like p←{(↑⍵)∘{(⍺∨.=⍵)/⍳n×n∘}¨,⍵},(n*÷2){⍵,⍺⊥⌊⍵÷⍺}'⍳n n←⍴⍵ It re…

Late to the game here but...

> can you find the bug?

Several stand out immediately:

- Two syntax errors: unclosed single quote in '⍳n n←⍴⍵ and no right operand in the second use of Jot (∘). It's not clear how those could have snuk in naturally by accident, but I'll just assume cosmic rays and that they should be simply elided.

- n n←⍴⍵ is setting n twice, which is a bit surprising, though it signals that you probably expect ⍵ to have rank 2. In such cases _ n←⍴⍵ or n←⊃⌽⍴⍵ may be more natural, depending on intent.

- However, Decode (⊥) will error if ⍴⍵ returns anything other than a single integer (or an empty vector), so n n←⍴⍵ is equivalent to just n←⍴⍵ and doubly confusing.

- Which means that (n*÷2){⍵,⍺⊥⌊⍵÷⍺}⍳n n←⍴⍵ can only return a vector, i.e. 1..n with a number tacked on the end: the value of (1-x^n)/(1-x) evaluated at sqrt(n), which is a bit of a strange data structure IMHO. Something to do with geometric series of n^2?

- The second use of Ravel (,) in ,⍵ is redundant, and given the constraints we know above, so is the first use: ,(n*÷2)...

- It also means that (↑⍵) is the same as just ⍵

- But then (⍺∨.=⍵) is always just 1

- Meaning that the whole code is essentially equivalent to p←(n+1)⍴⊂⍳n×n←⍴⍵. I.e. it just outputs n+1 vectors of the integers 1 to n^2.

- Which, without context, is hard to guess intent, but that data structure feels a bit strange. Instead of a vector of uniform-length vectors, a matrix would be more efficient: (n+1)(n*2)⍴⍳n×n←⍴⍵. But that's just a matrix with rows that are all the same, so maybe we could just use the single vector (⍳2*⍨⍴⍵) directly?

Really, despite looking strange, once you learn the symbols and basic operations, APL is surprisingly straightforward. If you're on HN, then you're already smart enough to learn the basics easily enough.

Admittedly, though, becoming proficient in APL does take some time and learning pains. Once there, though, it does feel like a superpower.

Re: Arthur Whitney's one liner sudoku solver (2011)

#206
post #58

Most people are put off by the symbols, that wasn't really the issue I had. So I do love APL and arraylangs, and learning them was really helpful in a lot of other languages. But they never became a daily driver for me not because of the symbols, which were honestly fine if you stick with it long enough, but after about 3-4 years of dabbling on and off I hit a wall with APL I just couldn't get past. Most other langua…

The wall you describe is a legitimate problem with the current APL on-ramp. One of my talks last year was on this exact issue [0]. It's definitely not you.

That said, it's also really not a limitation with the languages either. In my experience, punching past that wall is exactly the process of making the paradigm click. It took me a good 500 hours hacking on my YAML parser prototype over the course of a year before the puzzle pieces began to click in place.

Those lessons are still percolating out, but it feels like some combination of 1) data-driven design principles, 2) learning how to concretely leverage the Iversonian characteristics of good notation [1] in software architecture, and 3) simple familiarity with idioms and how they express domain-specific concepts.

Feel free to contact me if you'd like to chat directly about this and overcoming the wall.

[0]:https://dyalog.tv/Dyalog23/?v=J4cg6SV92C4 [1]:https://www.jsoftware.com/papers/tot.htm

Re: Arthur Whitney's one liner sudoku solver (2011)

#207

Earlier quoted context omitted.

You're not wrong. It's very easy to get that impression when trying to learn the array languages. It's very easy for someone who's used these languages for a long time to look at a problem, and say "why did you use that really elaborate solution, when you can just use ⍸⍣¯1?". No one probably ever told you that ⍸ has an inverse, and how you could use it. Even today, after having worked in these languages for years, I…

Very nice! I like the readability-- not sure if thats just indicative of your style or the language, and the map construct is also nice. I don't remember any off-the-shelf map construct, at least not in Dyalog.

Dyalog doesn't have an explicit implementation for maps, but you get the same effect with column-major table stores and the implicit hashmap backing of the search-like primitives [0]. E.g.

    keys←'foo' 'bar' 'baz'
    values←1729 42 0.5721

    indexOf←keys∘⍳  ⍝ The dyadic ⍳ here is what builds a hashmap
Then you can use it like

    data←(values⍪¯1)[indexOf 'bar' 'bar' 'baz' 'foo' 'invalid' 'foo']
where ¯1 is just the value you want missing keys to map to. If you're okay erroring in that case, it can be left off. For map "literals", a syntax like the following gets you there for now:

    k v ←'foo' 1729
    k v⍪←'bar' 42
    k v⍪←'baz' 0.5721
In version 20, proper array literal notation [1] is landing, where you'll be able to do:

    keys  values←↓⍉[
    'foo' 1729
    'bar' 42
    'baz' 0.5721]
In practice, I suspect that this ends up being more ergonomic than actual maps would be in the language. That said K is all about maps and the entire language is designed around them instead of arrays like APL. IIRC, there was also some discussion on the J forums a while back about whether or not to have explicit hashmap support [2].

[0]:https://help.dyalog.com/19.0/#Language/Defined%20Functions%2...

[1]:https://aplwiki.com/wiki/Array_notation

[2]:https://groups.google.com/a/jsoftware.com/g/forum/c/VYmmHyRo...

Re: Arthur Whitney's one liner sudoku solver (2011)

#208
post #201

Earlier quoted context omitted.

First off, thanks for continuing this exchange with me. Text communication between strangers is fraught with miscommunication perils left and right, so hanging in there is a really nice gesture. Cheers. It's so weird, though. Everything disagreeable you point out with my comments, I kind of feel like is true of GP's comment. It casually dismisses the content of OP, injecting a strawman about a "metrics". Wore still,…

I appreciate that your tone is softening with me, and that you took the time to mention some positives. De-escalating from a potential misunderstanding is the right way to go. I’ve reread your comments, and they still read like an attack to me, while the top comment does not. You may feel like you’ve drawn a line, but the implications you made were quite clear. Calling it a dick move is a more direct attack, and talk…

Oh well. It's clear you read my posts as personal or uncouth attacks. I genuinely disagree and tried to explicate intent clearly, but c'est la vie. IMHO, it's helpful to separate out ideas and actions from identity, freeing us to deal with the former without mercy as needed.

That said, this exchange will definitely bounce around in my subconscious, so whether or not I explicitly agree, you've definitely moved the needle!

Anyway, whatever happened here, it was a genuine meeting of minds, so much obliged fellow HNer. Be well.

Re: Arthur Whitney's one liner sudoku solver (2011)

#209

Earlier quoted context omitted.

None of the primitives are necessarily too complicated, but off the top of my head things like /: \: (encode, decode), all the forms of @ \ / . etc, don't have directly equivalent numpy functions. Of course you could reimplement the entire language, but that's a bit too much work. Tables aren't niche, they're very useful! I looked at cloudpickle, and it seems to only do serialisation, I assume you'd need something el…

> None of the primitives are necessarily too complicated, but off the top of my head things like /: \: (encode, decode), all the forms of @ \ / . etc, don't have directly equivalent numpy functions. Of course you could reimplement the entire language, but that's a bit too much work. @ and . can be done in numpy through ufunc. Once you turn your unary or binary function into a ufunc using food = np.frompyfunc, you the…

Again, I'm not saying anything is impossible to do, it's just about whether or not it's worth it. 2 or 3 lines for all types for all overloads for all primitives etc adds up quickly.

I don't see how k/q tables are only superior in niche situations, I'd much rather (and do) use them over pandas/polars/external DBs whenever I can. The speed is generally overhyped, but it is significant enough that rewriting something from pandas often ends up being much faster.

The last bits about IPC and typed objects basically boil down to python being a better glue language. That's probably true, but the ethos of array languages tends to be different, and less dependent on libraries.

Post reply on HN