Ans Piter
Ans Piter

Reputation: 573

converting atom to uppercase (or lowercase) [SICStus]

I want to convert lowercase atom to uppercase (vice versa) with this predicate:

to_upper([], []) :-
   !.
to_upper([LC|LCAtom], [U|UAtom]) :-
   UC is LC-32, 

   char_code(U, UC),  % <-
   % List = [UC|UAtom],

   to_upper(LCAtom, UAtom).
   % atom_codes(Result, List),

Result:

| ?- to_upper("abc", X).
X = ['A','B','C'] ? ;
no

My problem is the output must be like this X = 'ABC'. not list , I think atom_codes/2 resolve this prb yet which line must replaced by them?

helP

Upvotes: 1

Views: 1168

Answers (2)

Ans Piter
Ans Piter

Reputation: 573

after some effort, i arrived to this solution :

Code :

%lowercase to uppercase 

to_upper(Atom,UAtom) :- atom_codes(Atom,CList),
                       ( foreach(C,CList),
                         fromto(Res,Out,In,[]) 
                         do
                            between(97,122,C),     % is_upper
                            C1 is C-32,
                            Out=[C1|In]
                        ),
                        atom_codes(UAtom,Res).


% uppercase to lowercase

to_lower(Atom,LAtom) :- atom_codes(Atom,CList),
                       ( foreach(C,CList),
                         fromto(Res,Out,In,[]) 
                         do
                            between(65,90,C),     % is_lower
                            C1 is C+32,
                            Out=[C1|In]
                        ),
                        atom_codes(LAtom,Res).

Result :

| ?- to_upper(abc,X).
X = 'ABC' ? ;
no

| ?- to_lower('ABC',X).
X = abc ? ;
no
| ?- 

Note : with to_lower/2 u need to put atom between ' '

EDIT CODE :

transform atom structure

char_to_lower(L,UChar)  :-  % <=> char_to_lower(-32)
                            between(0'A, 0'Z, L)-> 
                            UChar is L+32 ; 
                            UChar=L.

atom_to_lower(Atom,Res) :-  % <=> atom_to_upper
                            atom_codes(Atom,Codes),
                            maplist(char_to_lower,Codes,LCodes),
                            atom_codes(Res,LCodes).

test whether the atom in uppercase

is_upper(Atom) :- atom_codes(Atom,Codes),
                  (
                  foreach(C,Codes) 
                  do
                  \+between(0'a, 0'z, C)-> true;
                                           fail,!
                  ).

test whether the atom in lowercase

is_lower(Atom) :- \+is_upper(Atom),!.  % \+ <=> NOT(pred/N)

get the upper and lower atoms from list

get_upper(List,List_Upper) :- include(is_upper,List,List_Upper).

get_lower(List,List_Lower) :- include(is_lower,List,List_Lower).
                              % exclude(get_upper,List,List_Lower)


% get_upper_lower(+List,?ListUpper,?ListLower)

get_upper_lower(List, List_Upper,List_Lower) :- get_upper(List,List_Upper),
                                                 get_lower(List,List_Lower).
                                              % get_lower/2 <=> exclude(get_upper,List,List_Lower)

Upvotes: 0

CapelliC
CapelliC

Reputation: 60024

I've shown in another answer a cleaner (imho) possibility:

% if uppercase get lowercase
upper_lower(U, L) :-
  between(0'A, 0'Z, U), L is 0'a + U - 0'A.

make_lower(C, L) :- upper_lower(C, L) ; L = C.

can be used directly and easily or exported from an utility module. Just give it a name you like.

?- maplist(make_lower, "UpperCase", Codes),format('~s~n', [Codes]).

Note: with the - so basic - maplist/N, we should gain the ability to use the far more declarative CLP(FD) library:

upper_lower(U, L) :-
  U #>= 0'A, U #=< 0'Z, L #= U - 0'A + 0'a.

Upvotes: 1

Related Questions