% Prolog Programming Exercises

% Ex 1: Read a string of characters ended with a dot and display it.
exercise1 :-
    write('Enter a string ended with a dot: '),
    flush_output,
    read_until_dot(Chars),
    write('You entered: '),
    display_chars(Chars),
    nl.

read_until_dot(Chars) :-
    get_char(C),
    (   C = '.'
    ->  Chars = []
    ;   Chars = [C|Rest],
        read_until_dot(Rest)
    ).

display_chars([]).
display_chars([C|Cs]) :-
    write(C),
    display_chars(Cs).

% Ex 2: Calculate the arithmetic mean of two numbers given by the user.
exercise2 :-
    write('Enter first number: '),
    flush_output,
    read(N1),
    write('Enter second number: '),
    flush_output,
    read(N2),
    Mean is (N1 + N2) / 2,
    format('Arithmetic mean is: ~w~n', [Mean]).

% Ex 3: Calculate the length of the circle and the area of the disc with the radius specified by the user.
exercise3 :-
    write('Enter radius: '),
    flush_output,
    read(R),
    Length is 2 * pi * R,
    Area is pi * R * R,
    format('Circle length: ~w~n', [Length]),
    format('Disc area: ~w~n', [Area]).

% Ex 4: Load a list of items until "end" is entered, and then display the list.
exercise4 :-
    write('Enter items (type "end." to stop):'), nl,
    read_items(Items),
    write('Created list: '),
    write(Items), nl.

read_items(Items) :-
    write('> '),
    flush_output,
    read(Item),
    (   Item = end
    ->  Items = []
    ;   Items = [Item|Rest],
        read_items(Rest)
    ).

% Ex 5: Read text entered by the user and save it in a file with the name indicated in the program code.
exercise5 :-
    Filename = 'output.txt',
    write('Enter text to write to file: '),
    flush_output,
    read_line(Chars),
    open(Filename, write, Stream),
    write_chars_to_stream(Stream, Chars),
    close(Stream),
    format('Text successfully written to ~w~n', [Filename]).

read_line(Chars) :-
    get_char(C),
    (   C = '\n'
    ->  Chars = []
    ;   Chars = [C|Rest],
        read_line(Rest)
    ).

write_chars_to_stream(_, []).
write_chars_to_stream(Stream, [C|Cs]) :-
    put_char(Stream, C),
    write_chars_to_stream(Stream, Cs).

% Ex 6: Read contents of a file and save in second file, converting to uppercase.
% Helper to copy and convert to uppercase
copy_and_uppercase(InFile, OutFile) :-
    open(InFile, read, InStream),
    open(OutFile, write, OutStream),
    process_streams(InStream, OutStream),
    close(InStream),
    close(OutStream).

process_streams(InStream, OutStream) :-
    get_char(InStream, Char),
    (   Char = end_of_file
    ->  true
    ;   upcase_atom(Char, UpperChar),
        put_char(OutStream, UpperChar),
        process_streams(InStream, OutStream)
    ).

% 6a) File names given in the program code.
exercise6a :-
    InFile = 'input.txt',
    OutFile = 'output_upper.txt',
    copy_and_uppercase(InFile, OutFile),
    format('Copied ~w to ~w in uppercase.~n', [InFile, OutFile]).

% 6b) File names are read from the user.
exercise6b :-
    write('Enter source filename (with quotes, e.g. \'input.txt\'.): '),
    flush_output,
    read(InFile),
    write('Enter destination filename (with quotes, e.g. \'output_upper.txt\'.): '),
    flush_output,
    read(OutFile),
    copy_and_uppercase(InFile, OutFile),
    format('Copied ~w to ~w in uppercase.~n', [InFile, OutFile]).