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édfü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

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;
}