Nemrég kriz kérte, hogy csináljak egy olyan cikket is, ahol C++, Prolog, SML összehasonlítások vannak :) Nos most hirtelen egy jut eszembe, nálunk volt zh példa. Van egy bemenő listánk és ebből kell kiszűrni az első pithagoraszi számhármast.

% Prolog
% A léptetés miatt kétszer adom át a listát, egyéb segéd-
% függvényekkel lehet máshogy is de beépített függvények 
% nincsenek, csak tanítanak néhány alapot, de ezekre most
% nem térnék ki, és nem is alkalmazok.

pith(L,P):- getpith(L,L,P).

% Gyorsan leírom a listákat hogy tiszta legyen, alapvetően 
% kétféleképpen lehet listákat leírni, az első: [A,B], ez 
% egy két elemű lista, ami tulajdonképpen 3 elemű. Na ezt 
% adjátok össze :) szóval, az első, tehát az A az mindig az
% első elem, a B pedig egy másik kételemű lista, aminek első 
% eleme a B, a második eleme pedig a [], tehát az üres lista.
% A második típus a listáknál a [A|B] kinézetű, ez annyit 
% tesz, hogy A a lista első eleme, B pedig az utána lévő 
% összes többi. pl. ha ezt adjuk rá: [1,2,3,4,5] vagyis egy 
% 5 elemű listát akkor az A = 1, és a B = [2,3,4,5] vagyis 
% 4 elemű lista. Ezen kívül még egy elem látható, a '_', 
% ez minden karakter lehet, tehát ez egy olyan, amit 
% figyelmen kívül hagyunk. Ennyit a listák bevezetéséről :)
% A két listát máshogy dolgozom fel, az A,B,C a lista első 
% három eleme mindig. A második lista az első elemen kívül
% mindent tartalmaz, tehát a léptetést szolgálja a mi 
% esetünkben, de mint említettem erre már vannak kifinomultabb
% technikák is, de beépített függvény nincs. Ezen felül a P 
% a visszatérési érték. A ZH-ban egy struktúraként kellett 
% visszaadni a megtalált számhármast, ezért most egy kicsit 
% a struktúrákról is: A struktúrák abban különböznek a 
% függvényektől, hogy nincs testük, tehát pl. p(A,B,C). 
% Függvénynév, argumentumok, és egy '.' :)
% Még egy új elem, amit eddigi prolog tudásotok még nem 
% tartalmaz, hogy prologban az if-then-else így néz ki: 
% ( feltétel -> igaz ág ; hamis ág )

getpith([A,B,C|_],[_|D],P):-   % függvény kezdete 
   (                           % feltétel kezdete
   A > 0 ,                     % A,B,C > 0
   B > 0 , 
   C > 0 , 
   A < B ,                     % A < B < C
   B < C , 
   X is A*A+B*B,               % A*A+B*B=C*C - vizsgálat
   Y is C*C,                   %  előtt a kiértékelődés
   X = Y                       %  miatt két változót használok
   ->                          % igaz ág
   P = p(A,B,C)                % a 3 szám p struktúrában
   ;                           % hamis ág
   getpith(D,D,P)              % a következő 3 elem vizsgálata
   )                           % if-then-else vége
.                              % függvény vége

% Tömörebben: getpith([A,B,C|_],[_|D],P):- (A>0,B>0,C>0,A<B,B<C,X is A*A+B*B,Y is C*C,X=Y->P=p(A,B,C);getpith(D,D,P)).

% Használat: 
% pith([1,3,5,3,7,24,25,8,7],P).
% Várt eredmény:
% P = p(7,24,25)

SML-ben most hirtelen nem is tudom van-e comment, nem rémlik, hogy láttam volna, úgyhogy inkább ide írom, a hozzászólásokat :) Tehát SMLben máshogy működnek a listák, egy kicsit ezekről: a listák formailag ugyanolyanok, de a függvényekben másként lehet szétszedni őket, amint látható. Most n1 az első elem, n2 a második, n3 a harmadik, ns pedig az összes többi. Az operátor ami ezek között van op:: egy listába fűzi össze a tagokat, így a léptetés is jóval egyszerűbb, ahogy az else ágnál is látszik; szándékosan nem szedtem szét több sorba, mivel lényegében ugyanaz, mint a prolognál. A további különbségek, hogy itt normális if-then-else szerkezet van, csak ugye még a then-t is ki kell írni :) illetve az andalso a sima 'és' kapcsolatot hivatott jelképezni, and-jellel nem megy a dolog, próbáltam kettővel és hárommal is :D igazából hárommal jó lenne, csak akkor más formában kéne, de erről most nem beszélnék, így egyszerűbb. A prologgal ellentétben itt egy listát adunk vissza, mivel nincs olyan struktúra, mint prologban, és ide nem is kell külön X, és Y a másodfokú egyenlethez, mivel az '='-nél kiértékelődik a két oldal :) Még két újdonság lehet, a függvény végén a '| pith _ = []', ami azt jelenti, hogyha a legelső argumentumra nem illeszkedik a bemenet, akkor egy üres lista lesz az eredmény. Tehát ha n1::n2::n3::ns -re nem négyelemű lista jön, ami lehet 3 érték és egy üres elem, akkor átugrik a másik lehetőségre pith _ -ra, ahol a _ a prologhoz hasonlóan a bármit jelenti. Erről azt hiszem eleget is beszéltem. Aztán pedig a függvényhívást így is el lehet végezni, kicsit rövidebben, mint az SML bevezetőben írtam, tehát nem kell 'val x =' az elejére, ilyenkor azt kapjuk, hogy az 'it'-nek az eredménye amit kaptunk, magyarán, "valami pont annyi amennyi a függvény értéke" :D Az utolsó sor végén pedig láthatjuk hogy ez egy int lista.

fun pith(n1::n2::n3::ns) = ( if n1 > 0 andalso n2 > 0 andalso n3 > 0 andalso n1 < n2 andalso n2 < n3 andalso n1*n1+n2*n2=n3*n3 then [n1,n2,n3] else pith(n2::n3::ns)) | pith _ = [];
> val pith = fn : int list -> int list
pith([1,3,5,3,7,24,25,8,7]);
> val it = [7, 24, 25] : int list
/* C++ megvalósítás */
/* Ennek a működését remélem nem kell ecsetelnem :) próbáltam 
Prologhoz hasonlóan struktúrában visszaadni a pith() 
visszatérési értékét, azt hiszem eléggé jól látható, 
hogy mi is a prolog és sml pozitívuma cpp-vel ellentétben :) 
azt hiszem a listakezelésük egy csöppet veri a cpp-ét, 
legalábbis rövidségben, és hatékonyságban :) */

#include <iostream>

using namespace std;

struct p { int a,b,c; };

p pith(int a, int b, int c) {
   p tmp;
   tmp.a=0;
   tmp.b=0;
   tmp.c=0;
   if(a>0&&b>0&&c>0&&a<b&&b<c&&(a*a+b*b==c*c)) {
      tmp.a=a;
      tmp.b=b;
      tmp.c=c;
   }
   return tmp;
}

int main() {
   int listaelemek[8];
   listaelemek[0]=1;
   listaelemek[1]=3;
   listaelemek[2]=5;
   listaelemek[3]=3;
   listaelemek[4]=7;
   listaelemek[5]=24;
   listaelemek[6]=25;
   listaelemek[7]=8;
   p tmp;
   for(int i=0;listaelemek[i+2]!=0;i++) {
      tmp=pith(listaelemek[i],listaelemek[i+1],listaelemek[i+2]);
      if(tmp.a!=0) { 
         cout << "p(" << tmp.a << ",";
         cout << tmp.b << "," << tmp.c << ")"; 
         break; 
      }
   }
   return 0;
}