Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

practical prolog - data processing

3 views
Skip to first unread message

metaperl

unread,
Nov 9, 2009, 3:56:57 PM11/9/09
to
How would you write a program which received numbers on STDIN, one per
line and then placed single quotes around each number, and then
parentheses around that?

Here is the Perl solution and output:

/* PROGRAM */

my @num = <>;

chomp $_ for @num; # remove newline from each number

@num = map { sprintf "'%s'", $_ } @num ;

my $paren = sprintf '(%s)', join ',', @num;

print $paren;

/* TRANSCRIPT */

[tbrannon@Ghostdc7600] [~/prg/prolog/comp.lang.prolog] perl makein.pl
050016411
050016412
050016409
050016410
050016407
050016408
050016405
050016406
('050016411','050016412','050016409','050016410','050016407','050016408','050016405','050016406','')

Jan Wielemaker

unread,
Nov 9, 2009, 4:22:24 PM11/9/09
to

Its of course Perl's strength, but it isn't that bad in (SWI-)Prolog:

================================================================
#!/home/jan/bin/pl -q -g run,halt -s

run :-
read_numbers(List),
maplist(number_quoted_atom, List, Quoted),
atomic_list_concat(Quoted, ',', Atom),
format('(~w)~n', Atom).

number_quoted_atom(Number, Atom) :-
atomic_list_concat(['\'', Number, '\''], Atom).

read_numbers(List) :-
read_line_to_codes(current_input, Line),
read_numbers(Line, List).

read_numbers(end_of_file, []) :- !.
read_numbers(Line, [H|T]) :-
number_codes(H, Line),
read_line_to_codes(current_input, Line2),
read_numbers(Line2, T).
================================================================

./x
|: 050016411


|: 050016412
|: 050016409
|: 050016410
|: 050016407
|: 050016408
|: 050016405
|: 050016406

|: ('50016411','50016412','50016409','50016410','50016407','50016408','50016405','50016406')

For the portability note: atomic_list_concat is supported by a few Prolog's.
read_line_to_codes/2 is from the SWI-Prolog library. format/2 is supported by
many more and the rest is ISO (oh, that is only number_codes/2 :-()

Cheers --- Jan

Mats Carlsson

unread,
Nov 10, 2009, 3:59:37 AM11/10/09
to
On Nov 9, 10:22 pm, Jan Wielemaker <j...@hppc323.few.vu.nl> wrote:

> On 2009-11-09, metaperl <scheme...@gmail.com> wrote:
>
>
>
> > How would you write a program which received numbers on STDIN, one per
> > line and then placed single quotes around each number, and then
> > parentheses around that?
>
> > Here is the Perl solution and output:
>
> > /* PROGRAM */
>
> > my @num = <>;
>
> > chomp $_ for @num; # remove newline from each number
>
> > @num = map { sprintf "'%s'", $_ } @num ;
>
> > my $paren = sprintf '(%s)', join ',', @num;
>
> > print $paren;
>
> > /* TRANSCRIPT */
>
> > [tbrannon@Ghostdc7600] [~/prg/prolog/comp.lang.prolog] perl makein.pl
> > 050016411
> > 050016412
> > 050016409
> > 050016410
> > 050016407
> > 050016408
> > 050016405
> > 050016406
> > ('050016411','050016412','050016409','050016410','050016407','050016408','050016405','050016406','')
>
> Its of course Perl's strength, but it isn't that bad in (SWI-)Prolog:

Here is a shorter version in SICStus with logical loops:

main :-
read_line(Head),
atom_codes(A, Head),
read_line(Line),
( fromto(Line,L1,L2,end_of_file),
fromto(A,A1,A2,Last),
fromto(Term,(A1,T2),T2,Last)
do atom_codes(A2, L1),
read_line(L2)
),
format("(~q)\n", [Term]).

| ?- main.
|: 123
|: 234
|: 345
|: 456
|: 567
|: ('123','234','345','456','567')
yes

Jan Wielemaker

unread,
Nov 10, 2009, 4:35:16 AM11/10/09
to

Cute, but you are cheating a little. You do not read numbers, but rely
on the fact that an atom containing digits gets quotes when written
using ~q ...

Cheers --- Jan

Ulrich Neumerkel

unread,
Nov 10, 2009, 9:11:58 AM11/10/09
to
metaperl <sche...@gmail.com> writes:
>How would you write a program which received numbers on STDIN, one per
>line and then placed single quotes around each number, and then
>parentheses around that?

Since you give a pure input/output specification, you should receive
-ideally- also a pure solution in Prolog.

For the input part you can use library(pio) of SWI Prolog.

I.e, you can parse the file directly with a DCG. My favorite is
grep:

... --> [] | [_], ... . % That should be in a library

?- phrase_from_file(file, (...,"the search string",...)).

Now succeeds if file contains the search string.

That is not as comfortable as Perl, but I am quite
convinced that what is lacking here are just some nice libraries.

Feel free to consider some.

The output part will be covered by pio as well. But to make
it stable takes some time.

afa

unread,
Nov 10, 2009, 11:33:01 AM11/10/09
to
On Nov 9, 3:56 pm, metaperl <scheme...@gmail.com> wrote:

How about this one?

main :-
readLine(First),
loop('(',First,_).

loop(_,[],DoOut):-!,DoOut=go,writeln(')').
loop(Deli,Line,DoOut):-
freeze(DoOut,format("~w'~s'",[Deli,Line])), % don't do the output
until DoOut is nonvariable
readLine(NLine),
loop(',',NLine,DoOut).

Cheers,
Neng-Fa

YauHsienHuang

unread,
Nov 10, 2009, 11:54:53 AM11/10/09
to
On Nov 10, 4:56 am, metaperl <scheme...@gmail.com> wrote:
> How would you write a program which received numbers on STDIN, one per
> line and then placed single quotes around each number, and then
> parentheses around that?
......

> [tbrannon@Ghostdc7600] [~/prg/prolog/comp.lang.prolog] perl makein.pl
> 050016411
> 050016412
> 050016409
> 050016410
> 050016407
> 050016408
> 050016405
> 050016406
> ('050016411','050016412','050016409','050016410','050016407','050016408','0 50016405','050016406','')

Operations on input stream cause side effects, that is a general
concept accepted by functional programming language programmers. In
Prolog, backtracking would not work after reading an item from the
input stream. So I wrote my sequence reading program in the following
fashion.

read_sequence(Z) :-
read(X),
( X == end, Z = nil, !;
number_chars(X, X1), atoms_concat(X1, X2),
read_sequence(Y), ( Y == nil, Z = (X2), !;
Z = (X2, Y)
)
).
atoms_concat([], '').
atoms_concat([X|Y], Z) :-
atoms_concat(Y, Y1),
atom_concat(X, Y1, Z).

------------------------------
?- read_sequence(X).
| 050016411.
| 050016412.
| 050016409.
| 050016410.
| 050016407.
| 050016408.
| 050016405.
| 050016406.
| end.
X = ('50016411', '50016412', '50016409', '50016410', '50016407',
'50016408', '50016405', '50016406').

It seems fine. However, every item in input sequence was treated as a
number but an atom, and the leading zero of every item was eliminated.
How to correct it?

0 new messages