Whenever you see an error message complain about an undefined identifier named "_R", that's because of a long-standing issue with the Racket reader in Windows terminals. If you paste multiple lines into the terminal, what you paste needs to have a blank line at the end already or else Racket will think it sees an R somewhere in the middle of your code.
It's not your fault. It's a bummer to have to work around this.
BTW, you can always simplify (if <expression> nil t) to just (no <expression>).
Also, what's that i variable doing in valid?? I don't understand how valid? works..
You _really_ don't want to be making pass-by-reference changes like incrementing i inside some, since there's no guarantee about the order in which it'll run. If you want imperative updates, just use an explicit loop like each.
Yeah, I should have explained more. I'd planned the results to be in the form:
((row col) (row col) (row col) ...)
Your version works just as well :) but the variable names might make a little more sense this way.
a) (o queens) means that queens is an optional argument. If I don't pass in a value it's nil by default. I could also have given it an explicit default by saying (o queens 42). You can read more about this in the tutorial: http://www.arclanguage.org/tut.txt. Worth a reread if it's been a while.
b) queens.0.0 expands to ((queens 0) 0). Which is the same as (car (car queens)). Just a quick way to pull out the first row, the row of the most recently added queen (since I'm adding queens on the left using cons).
c) col is just a variable name for the column in the above representation of queens. But perhaps you were asking about up. Try this out at your Anarki prompt:
arc> (help up) ; only in Anarki
arc> (up col 0 8 (prn col))
d) some takes a predicate (function) and a list, and returns true if any of the elements of the list is satisfied by the predicate (function returns true). Check out (help some), as well as the tutorial above. One twist is that you can pass in any number/character/boolean as a predicate, and it's as if you're comparing with it. So I'm asking "have we already seen this column?" in this line:
(some curr-column (map [_ 1] rest))
e) Yes, no is like ~ though not quite the same. It's just simple boolean negation. (no nil) is t, no on anything else is nil. ~ (complement) is slightly different, it operates on functions and makes them return their negation. So this relation always holds:
(no f.x) <=> (~f x)
I could have written (no conflicts.new-queens) as (~conflicts new-queens).
(do
(let (diagonals2 result2 total2)
(print-result diagonals2 result2 total2)
(= diagonals diagonals2 result result2 total total2)))
There must be a way for the system to realize I expect (print-result) to update diagonals, result and total, so it automatically creates diagonals2/result2/total2, puts them in a let statement as the receivers of the return value of (print-result) and upon coming back from (print-result) automatically the system automatically sets diagonals/result/total to each element of the return list.
Thanks, I'm familiar with that practice. I'm also used to passing by reference so that changes made to the variable in the newer function get passed back to the calling function.
Yeah, makes sense. However, let always creates a new binding and never modifies existing bindings. That's why it makes you indent its body to the right. Compare:
(= x 3 y 4)
(+ x y)
with:
(let (x y) '(3 4)
(+ x y))
The indentation is a hint that these are new x and y variables, compared to any earlier x and y variables.
Besides let there are indeed functions in Arc where you can pass lists or tables by reference (though not primitives like numbers or characters). However, it's usually a good idea to try to avoid these, again so you can practice a less imperative style of programming (http://arclanguage.org/item?id=19709). My usual approach is to first build a program with promiscuous copying everywhere, and then if it turns out to be too slow pick the 2% of cases that can speed it up a lot and make them destructive/call-by-reference, because the cost of doing so is that it makes the program harder to understand.
There's still other functions that are missing, such as goto-next-column, goto-previous-column, etc.
Anyways, I think you've gotten me to work on this problem as well :) I found it super hard when I solved it in C back in '97. Perhaps I should go back and see if I've gotten any better at programming.
So if two results were (2 4 1 3) and (3 1 2 4), both of them sort to (1 2 3 4) so delete one of them? Of course all of the results will sort to (1 2 3 4) for a 4x4 board.
Thanks! I think I'll try to solve it on my own without looking at yours in depth first. That might take me a few days. But feel free to keep asking questions in the meantime.
This took me too many hours in my work language to solve. Initially I next just translated it to arc, but that didn't seem to work, so I started again in arc from scratch. I sure learned a lot about arc and debugging in it.
It took me a while to wrap my mind around this problem. Sure is different than CRUD work, reports and interfaces.
Here's a newer view. A number of variables (diagonals, result, row, total) get modified lower in the function. There must be a better way of updating those variables.