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│
└───┘
Related
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
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
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
I'm following along this thing: J Dictionary
It tells me to issue the command d by d over d!/d where d is a list, but my jqt environment tells me value error: over. If the problem is that I'm supposed to import/install/activate a library, I don't see any instructions in the documentation about that. Anyone know what's going on here?
From the documentation you linked:
The verbs over=:({.;}.)#":#, and by=:' '&;#,.#[,.] can be entered as utilities (for use rather than for immediate study)
It's telling you to define those verbs in order for the following code to work.
So they're not part of the standard library nor any other library - you're supposed to define them yourself.
When messing around with Haskell using GHC, I can use various meta-commands like :i or :t to find out some information about an identifier. In REBOL, I can use functions like help and sometimes source to get extremely detailed information on a REBOL word.
If such a facility exists for J, I've somehow missed it. Do any J-ers out there know of anything built-in?
Highlight the primitive or J library verb and hit Ctrl-F1. Instant help in html form in your browse if it's a primitive, script documentation for J library verbs.
EDIT:
Or you can use the verb defined to do that, help_j_:
help_j_ 'i.' NB. Opens didot.htm
help_j_ 'help_j_' NB. Opens \system\extras\util\jadefull.ijs in scriptdoc