Why do two similar J verb phrases work, but only one of them works with the dynamic power conjunction? - j

The verb chain ''-:] works the way I would expect.
(''-:])''
1
(''-:])'non-empty'
0
It also works the way I expect with the dynamic power conjunction.
'empty'[^:(''-:])''
empty
'empty'[^:(''-:])'non-empty'
non-empty
The verb phrase ''&-: produces the same results, as I would expect.
(''&-:)''
1
(''&-:)'non-empty'
0
When I try to use ''&-: with the dynamic power conjunction, J produces a domain error and I don't understand why. What's the difference between this use case and all of the others?
'empty'[^:(''&-:)''
|domain error
| 'empty' [^:(''&-:)''
'empty'[^:(''&-:)'non-empty'
|domain error
| 'empty' [^:(''&-:)'non-empty'
Is the message below the line "domain error" trying to tell me anything specific?
My actual use case is to replace empty strings with another string. If anyone has any suggestions for better ways to do that, I would appreciate it.

Good question and one that had me digging into my Nuvoc reference for (^:) Power Conjunction https://code.jsoftware.com/wiki/Vocabulary/hatco#Common_Uses_2
I refer to Nuvoc since that is the reference now being used instead of the J vocabulary.
As far as I can tell the issue is that you have a dyadic function (your arguments are 'empty' and '') and you are trying to force it to be monadic with your test (''&-:)
'empty'[^:(''&-:) ''
|domain error
| 'empty' [^:(''&-:)''
Domain error often show up when you don't have the right number of arguments, or the arguments that you are using are a type that is not appropriate.
If we change your test to a fork ('' -: ]) it works because now the x and the y arguments are being handled appropriately. The ] selects the y argument and the noun on the left tine does not require arguments.
'empty'[^:(''-:]) '' NB. turn the test into a fork
empty
Another way that works is to change the x argument into a verb using "_ which creates a verb of infinite rank and when invoked will return the result that you are expecting. This again gets rid of the problem of the dyadic monadic confusion so that your original test now works. Parentheses around empty"_ are required to separate the power conjunction ^: from the verb.
('empty'"_) ^:(''&-:) '' NB. turn the x argument into a verb
empty
Other approaches that you might take are to look at the Amend adverb } https://code.jsoftware.com/wiki/Vocabulary/curlyrt#dyadic

Related

Generating Solution Candidates For Matching People in Clingo/ASP

I have a list of people and I want to pair them all then do some filtering based on preferences. When I generate my candidate solutions, how do I avoid creating candidate solutions that re-pair a people.
For example:
person(a;b;c;d) .
{match(X, Y): person(Y)}1 :- person(X) .
This generates candidate solutions that include match(a,b) match(c,b) ...
I would like ONLY candidate solutions that do not rematch anyone like: match(a,b) match(c,d) ...
My goal is to not have to filter rematches out via additional constraints. Also, not everyone needs to be matched. Thanks!
person(a;b;c;d).
{match(A,B) : person(A), person(B), A < B}.
:- person(A), 1 < {match(A,B); match(B,A)}.
You exclude solutions that have more than 1 match for a single person.
It is not possible to simply choose a correct set of atoms without additional constraints. As match(a,b) and match(b,c) can occur in different answer sets, both variables need to be created. Only a constraint can rule out that both do not occur in the same answer set.
Also note that your generator rule
{match(X, Y): person(Y)}1 :- person(X) .
already is a shortcut writing for
{match(X, Y): person(Y)} :- person(X).
:- person(X), 2 {match(X, Y): person(Y)}.
And therefore you are already using a constraint whenever your generator choice rule has non-trivial bounds.
PS: Check the different versions using --stats=2 for constraint count and --text for a rough approximation of what kind of constraints are generated.
I'd go for Max Ostrowskis answer.
One of the difficulties is to handle the order of the attributes for the match predicate: this is a tuple, there is a difference if your value shows up on first or second position. Adding a rule to make the predicate commutative should do the trick since you don't need to distinguish for a value to be on first or second position. This method does not use a constraint (on first sight), but it duplicates the generated values so the output differs from your desired solution. Also it adds a line to the code.
person(a;b;c;d).
{match(X,Y): person(Y), X!=Y}1 :- person(X).
match(Y,X) :- match(X,Y).
#show match/2.
Output
Answer: 1
Answer: 2
match(c,a) match(a,c)
Answer: 3
match(b,a) match(a,b)
Answer: 4
match(c,d) match(d,c)
Answer: 5
match(b,a) match(a,b) match(c,d) match(d,c)
Answer: 6
match(b,d) match(d,b)
Answer: 7
match(c,a) match(a,c) match(b,d) match(d,b)
Answer: 8
match(b,c) match(c,b)
Answer: 9
match(d,a) match(a,d)
Answer: 10
match(d,a) match(a,d) match(b,c) match(c,b)
SATISFIABLE

SML Pattern Matching on char lists

I'm trying to pattern match on char lists in SML. I pass in a char list generated from a string as an argument to the helper function, but I get an error saying "non-constructor applied to argument in pattern". The error goes away if instead of
#"a"::#"b"::#"c"::#"d"::_::nil
I use:
#"a"::_::nil.
Any explanations regarding why this happens would be much appreciated, and work-arounds if any. I'm guessing I could use the substring function to check this specific substring in the original string, but I find pattern matching intriguing and wanted to take a shot. Also, I need specific information in the char list located somewhere later in the string, and I was wondering if my pattern could be:
#"some useless characters"::#"list of characters I want"::#"newline character"
I checked out How to do pattern matching on string in SML? but it didn't help.
fun somefunction(#"a"::#"b"::#"c"::#"d"::_::nil) = print("true\n")
| somefunction(_) = print("false\n")
If you add parentheses around the characters the problem goes away:
fun somefunction((#"a")::(#"b")::(#"c")::(#"d")::_::nil) = print("true\n")
| somefunction(_) = print("false\n")
Then somefunction (explode "abcde") prints true and somefunction (explode "abcdef") prints false.
I'm not quite sure why the SML parser had difficulties parsing the original definition. The error message suggests that is was interpreting # as a function which is applied to strings. The problem doesn't arise simply in pattern matching. SML also has difficulty with an expression like #"a"::#"b"::[]. At first it seems like a precedence problem (of # and ::) but that isn't the issue since #"a"::explode "bc" works as expected (matching your observation of how your definition worked when only one # appeared). I suspect that the problem traces to the fact that characters where added to the language with SML 97. The earlier SML 90 viewed characters as strings of length 1. Perhaps there is some sort of behind-the-scenes kludge with the way the symbol # as a part of character literals was grafted onto the language.

J string manipulation using only builtins

You are given a string like ))()(())(, and you wish to remove all instances of () from the string, which in this case means these two instances:
))()(())(
^^ ^^
leaving only ))()(.
I know you can use the library function stringreplace, or you could load up a regex library, but I want to know is if there is a concise way of accomplishing this the the J builtin operators exclusively?
I should clarify that my own solution was:
#~(-.#+._1&|.)#('()'&E.)
which I consider verbose -- so any similar solutions would not qualify as "concise" in my book. I'm really asking if there is a way to use a builtin (or maybe a simple combination of 2) to solve this directly. I expect this answer is no.
I think you are right that there is no ultra-concise way of expressing the operation you want to perform using just J primitives. The version I came up was very much like the one Dan, suggested above.
However given that a built in library verb rplc (based on stringreplace) performs exactly the operation you are after, I'm not sure why it would be better to replace it with a primitive.
'))()(())(' rplc '()';''
))()(
Having said that, if you can come up with a compelling case, then there is probably no reason it couldn't be added.
Not sure how concise it is, but I think that this will work:
deparen=. (-.#:(+/)#:(_1&|. ,: ])#:E. # ])
'()' deparen '))()(())('
))()(
Essentially the work is done by -. #: (+/) #: (_1&|. ,: ] )#:E. to create a bit string that removes the '()' instances using # (Copy) on the right argument.
E. identifies the positions of '()' using a bit string. Shift and laminate to get positions of '(' and ')', add them together to have 1 1 in the string where ever there is a '()' and then negate so these positions become 0 0 and are removed using Copy

Groovy optional parentheses and dots

I am learning Groovy and am pretty impressed with how it allows one to build a intelligent DSL, but I am a bit confused by the rules for when parentheses and dots are optional. Consider the following code:
Integer take(Integer x) {x}
take 3 plus 4
This works as expected and produces an output of 7 (when ran in the console), as groovy understands that last line as take(3).plus(4).
Now, println take 3 plus 4 does not work as groovy understands that as println(take).3(plus).4 which is nonsense.
Every example that I am seeing shows these sort of expression by themselves on a line, but apparently
s = take 3 plus 4
works and stores the result 7 in s. My question is, why does
println( take 3 plus 4 )
not work? Obviously, groovy will parse these sort of expressions even if they are not by themselves on a line (as shown by the assignment working). I would have thought that adding those parentheses would remove the ambiguity from the form of that line that doesn't work and that it would print out 7 as I intended.
Instead groovy gives an error 'unexpected token: 3'. As far as I can tell, groovy will not allow optional parentheses or dots inside that println, even though it doesn't seem to be ambiguous. When exactly does this sort of trick work?
This falls into the category of a nested method call, and in that case you cannot omit the parentheses. This is causing ambiguity and the results are unexpected, as the println method thinks you are passing it multiple parameters. You could reduce the ambiguity by using a groovy string in the println method.
println "${take 3 plus 4}"
More info: Omit Parentheses

strange results on composing verbs in J

I am wondering why the following failed to work.
(1=$:#([:+/[:*:#"."0":)`]#.(e.&1 4))7
1
and
(({&('no';'yes'))#(1=$:#([:+/[:*:#"."0":)`]#.(e.&1 4)))7
┌──┐
│no│
└──┘
I would expect it to return yes since it is taking the second argument (because the first expression evaluates to 1). Could anybody please explain?
Thanks.
I must admit that it is difficult to figure out what you are trying to do, but the issue i think is your use of Self-Reference ($:).
The description of Self-Reference in the J dictionary states '$: denotes the longest verb that contains it.' http://www.jsoftware.com/help/dictionary/d212.htm
By combining
({&('no';'yes')) with your original verb
(1=$:#([:+/[:*:#"."0":)`]#.(e.&1 4))
You have actually changed the verb that $: self references and I believe this results in the (unexpected) behaviour. I hope that this helps. If you can give a reason for using $: I might be able to give a better answer as to why your verb works this way. I tend to use it very little, as there are usually better solutions in J.
Just another thought. You could define the parts of the verb you are looking to create separately and this would limit the scope of the $: and give you the behaviour that you would like.
choose=: (1=$:#([:+/[:*:#"."0":)`]#.(e.&1 4))
display=:({&('no';'yes'))
display # choose 7
┌───┐
│yes│
└───┘

Resources