We’re rewarding the question askers & reputations are being recalculated! Read more.

Hot answers tagged

6

Why fail at all? Isn't success better than failure? A shorter version is thus: main :- writeln('Hello world!'). Also, why even have side effects? Isn't a declarative solution much better: message('Hello World'). This way, you can also reason about the message within the program itself. This is not possible if it only appears as output on the terminal. ...


5

+1, good question. The Prolog convention is to use underscores for readability. Why? because_it_is_easy_to_read_even_long_names_with_underscores, butItIsExtremelyHardToReadEvenShorterNamesWithMixedCaps! A good naming convention is to use one noun per argument, declaratively describing what the argument stands for. In SWI-Prolog, check out library(pio): ...


5

Consider describing what a transition is: list_transition(List, (E1->E2)) :- select(E1, List, Rest), member(E2, Rest). Example query: ?- list_transition([0,1,2], T). T = (0->1) ; T = (0->2) ; T = (1->0) ; T = (1->2) ; T = (2->0) ; T = (2->1) ; false. And to get all transitions: ?- findall(T, list_transition([0,1,2], ...


4

sure: zipwithindex(List1, List2) :- findall(E/I, nth0(I, List1, E), List2). Edit - after Tudor' comment bagof/3 it's much better than findall/3, as it doesn't introduce unwanted new variables. This can be of utmost importance when working with constrained variables - i.e. CLP(FD) or CHR


4

I think you can simplify your code quite a bit if you drop the implicit restrictions you have on parent. Consider the following: parents(X,Y,Z) :- (father(X,Z), mother(Y,Z)); (father(Y,Z), mother(X,Z)). father(X,Y) :- parent(X,Y), man(X). mother(X,Y) :- parent(X,Y), woman(X). This gets rid of the implicit genders in your definitions (see your parents ...


4

The problem, as stated, has a completely straight-forward solution, because the problem statement is limited to numbers: sicp1(X, Y, Z, SumSquares) :- msort([X,Y,Z], [_,A,B]), SumSquares is A^2 + B^2. You can use this predicate every time the three numbers are fully specified, for example: ?- sicp1(1, 2, 3, S). S = 13. The problem though ...


4

A quick browse through the SWI-Prolog manual finds atomics_to_string/3: atomics_to_string(+List, +Separator, -String) Creates a string just like atomics_to_string/2, but inserts Separator between each pair of inputs. For example: ?- atomics_to_string([gnu, "gnat", 1], ', ', A). A = "gnu, gnat, 1"


4

Built-ins The function showTermList applies show to each item in the list (map show) and puts , [COMMA] between any two items of the list (intercalate ","). You can just use this predefined functions to write: showTermList = intercalate "," . map show Also in tokens: | isSpace c = tokens cs -- eat all whitespace Eating all white-space is better ...


3

Have some refactoring of your latest version, mostly to move the code closer to my tastes, YMMV. Take what you will. import Data.Char import Control.Monad import Control.Applicative import Control.Monad.Trans.State {- data structures -} data Term = Atom String | Number Int | Variable String | Complex String [Term] ...


3

Question Author's answer I accepted Caridorc's answer as it shows the canonical CR answer style and my original question doesn't seem to fit this forum very much. His/her suggestions are spot-on when it comes to making the original code better. Nonetheless, I figured it out and understood Monad and related concepts. I think it's really a clever idea to use ...


3

In the Logtalk library, you have a map_reduce/5 predicate: :- public(map_reduce/5). :- meta_predicate(map_reduce(2, 3, *, *, *)). :- mode(map_reduce(+callable, +callable, +term, ?list, ?term), zero_or_more). :- info(map/5, [ comment is 'Map a list and apply a fold left (reduce) to the resulting list.', argnames is ['Map', 'Reduce', 'Accumulator', '...


3

In SWI-Prolog you could do this that way: sample_swi(Domain, N, Sample) :- random_permutation(Domain, Permutation), length(Sample, N), append(Sample, _, Permutation). Be careful, this predicate is not a true relation (just as in your code).


3

As a general rule of thumb, you should avoid using the global database for such purposes. For example, in your case, after the predicate completes, counted_states/1 is still asserted, and will influence later invocations of the predicate. This certainly is not intended, no? There is a straight-forward solution for this: First, describe what it means ...


3

Please consider using format/2 for formatting output. You do not need so many concatenations! Also, check out the following sample query and interaction: ?- main([test]). test true ; test true ; false. This shows that internally, there are choice-points left, and in fact even alternative solutions. Ideally, the predicate should be deterministic, i.e., ...


2

Well, copying my answer from SO. Think about the number of outputs of subset/4, if every cell of Solution is unbound in the beginning. There are 44*4 = 4,294,967,296 outputs. Now you might know why your code is so slow. You should call valid/1 inside of subset/2. Test if the puzzle is still valid after inserting one number: subset(_,[],_). subset(RCS,[H|T]...


2

Quite nice! A few comments: First of all, consider using SWI-Prolog because it has more extensive libraries that you can use. In particular, consider using SWI's library(pio) to process files. Pure input lets you write DCGs and then transparently apply them to files, which leads to more declarative and more convenient solutions. Instead of isalpha/1 etc., ...


2

Executive summary: please_use_very_readable_names insteadOfUnreadableOneslikeInJava. Use higher-order predicates. Always consider using DCGs when describing lists. pass1 and pass2 can be simplified a lot with DCGS. Use format/2 instead of multiple write/1 calls. Examples: Higher order predicate maplist/2, replacing 4 almost identical member/2 calls: ...


2

Always try hard to avoid assert/1 and retract/1: Using these predicates makes it impossible to reason about your other predicates in isolation, and therefore make debugging and extending your code much harder. In this case, there is a clear declarative solution: Represent the state of all doors as a Prolog term, and thread this state through all predicates ...


2

Your concerns about style and format are warranted, +1 for striving to make the code more elegant and declarative! First of all, whatDoYouFindEasierToRead: mixed_caps_or_underscores? For that reason, using underscores is the Prolog convention for naming predicates. Second, Prolog is all about relations between things. You are using low-level moded ...


2

The best way to reason about integers is to use your Prolog system's CLP(FD) constraints. For example, in SICStus Prolog and SWI-Prolog: :- use_module(library(clpfd)). nearby(X, Y) :- abs(X - Y) #= 1. This works in all directions out of the box. For example, with both arguments integers: ?- nearby(1, 2). true. Second, with only one argument known: ?- ...


2

Your closest_common_ancestor/3 doesn't work, for instance, closest_common_ancestor(rose, fred, X). fails to find answers, however X=arthur and X=molly are both answers. Below is the version that would work: closest_common_ancestor(P1, P2, CCA) :- parent(CCA, P1), parent(CCA, P2). closest_common_ancestor(P1, P2, CCA) :- parent(P, P1), ...


2

Generally, a very good guidline when coding in Prolog is: Everything that can be expressed by pattern matching should be expressed by pattern matching. By this I mean that it is good practice to distinguish different cases symbolically in clause heads instead of using if-then-elses within bodies. Unfortunately, this guideline is hard to apply in this ...


2

Before discussing correctness, efficiency and alternative approaches, I first have three smaller suggestions to simplify the predicate a bit: Its seems I2 is nowhere really needed, you can always simply use J instead. for J2, I would stick to CLP(FD) constraints like: J2 #= J*10. instead of (\=)/2, I recommend to use dif/2. These changes make the code a ...


2

This is quite nice, but there are still several ways that would improve this. Here are a few ideas: Relations instead of side-effects First, I recommend to avoid side-effects. Instead, think in terms of relations. By this I mean that you should not use write/1 to print a solution, but express what constitutes a solution, as in the following: solution(...


2

Parsing is always a bit complicated/ugly in terms of code—a library like ANTLR can do some of the heavy lifting for you. But let's assume some level of reinventing-the-wheel for practice/exercise. Recommendations What follows are fairly broad recommendations based on the question: "If I were responsible for maintaining this code, what would I do?" Use ...


2

In my opinion, your code would benefit considerably from a better naming convention. In Prolog, a good predicate name makes clear what each argument denotes. For example, when I see: prereqs(460, 233). then I have no idea what the arguments are. I see it is about prerequisites, but in which direction? Is 460 a prerequisite of 233, or is it the other ...


1

On top of what mat mentioned, here are some general programming suggestions which also apply here: Give names to data-structures. You are using a list of lists to represent the solution. That's OK, but not every list of lists is of the shape of your solution. Also, dealing with low-level representation of the data-structure makes you write a lot of ...


1

Using global variables is a sure sign that you are not working within the declarative paradigm. A declarative way to solve this is to keep track of the already visited variables via an argument of your predicate. Also, please_use_a_readable_naming_convention insteadOfMakingEverythingHardToReadAsInJava. For example, suppose you have a relation ...


1

When describing lists, always consider using DCGs. In this case, try for example: sum(Xs0, Ys0, Ls) :- reverse(Xs0, Xs), reverse(Ys0, Ys), phrase(sum(Xs, Ys, 0), Ls0), reverse(Ls0, Ls). sum([], [], Carry) --> ( { Carry > 0 } -> [Carry] ; [] ). sum([X|Xs], [Y|Ys], Carry0) --> { N0 is X + Y + Carry0, ( ...


1

Yes, they are. Speaking Haskell, combine is pairwise, pairwise f (x:y:r) = f x y : pairwise f r pairwise _ xs = xs -- covers both [x] and [] cases and reduce looks like the tree-shape folding foldt f [x] = x foldt f xs = foldt f (pairwise f xs) Of course tree-shaped folding is algorithmically advantageous over the linear one. It's even possible to ...


Only top voted, non community-wiki answers of a minimum length are eligible