You are on page 1of 4

პრაქტიკული მეცადინეობა 2

სააუდიტორიო სამუშაო:
ამოცანა 1:
1) მოიყვანეთ ფუნქციის კოდი, რომელიც დაადგენს არის თუ არა მოცემულ ვექტორში
მოცემული p თვისების მქონე ელემენტი. დადებითი პასუხის შემთხვევაში ალგორითმმა
უნდა პირველივე (p-დან დაწყებული) ასეთი ელემენტის ინდექსი, წინააღმდეგ შემთხვევაში
კი ვექტორის ზომა (ანუ კონკრეტული არარსებული ინდექსი) .
2) მოიყვანეთ ფუნქციის გამოძახების რამდენიმე ვარიანტი სხვადასხვა ტიპის
ვექტორებისთვის. p თვისებას შესაძლოა წარმოადგენდეს როგორც მომხმარებლის მიერ
შექმნილი ბულის ტიპის უნარული (ანუ ერთადგილიანი) ფუნქცია, ასევე ფუნქციის
ადაპტერი.
ამოხსნა: ფუნქციას შესაძლოა ჰქონდეს სახე:
template<typename T, typename Predicate>
int my_search_if(const vector<T>& v, Predicate p)
{
int i = 0;
while(i != v.size() && p( v[i]) == false )
++i;
return i;
}
შეგვეძლო ეს ფუნქცია დაგვეწერა როგორც წინა მეცადინეობაზე, for შეტყობინებით. მაგრამ
მომდევნო ამოცანაში განსხვავება ამ ორ შეტყობინებას შორის არსებითია. ამიტომ ცნობილ
ალგორითმზე გადავიმეოროთ ასეთი მიდგომა.
მაგალითად, თუ ძირითად ფუნქციას შესაძლოა ჰქონდეს სახე:
nt main()
{
int mas[] = {12,3,26,7,11,213,7,123,-31};
int dim(sizeof(mas)/sizeof(int));
vector<int> v(&mas[0],&mas[dim]);

int k = my_search_if(v, bind2nd(greater<int>(),100));

if(k != v.size())
cout << "Found at index " << k << endl;
else
cout << "Not found!" << endl;

double masD[] = {18.2, 3.09, 26.21, 7.54, 11.1, 21.3,7.5, 123.54, -3.14};
int dimD(sizeof(masD)/sizeof(double));
vector<double> v1(&masD[0],&masD[dimD]);

k = my_search_if(v1, bind2nd(less<double>(),-1.0));

if(k != v.size())
cout << "Found at index " << k << endl;
else
cout << "Not found!" << endl;

return 0;
}
vector<int> v;
და
სტრიქონი
Page 1 of 4
int k = my_search_if(v, bind2nd(greater<int>(),100));

მოძებნის და შეინახავს პირველივე 100-ზე მეტ ი ელემენტის ინდექსს, ან ვექტორის ზომას.


ამიტომ, დაბეჭდვამდე საჭიროა შემოწმება:
if(k != v.size())
cout << "Found at index " << k << endl;
else
cout << "Not found!" << endl;
ანალოგიურად ხდება ძებნის ფუნქციის გამოყენება ნამდვილი ვექტორისთვის.
ფუნქცია პრედიკატად მიიღებს აგრეთვე ჩვეულებრივი მარტივი მეთოდებით შექმნილ
თვისებას. მაგალითად, თუ ჩვენ უკვე შექმნილი გვაქვს პრედიკატი
bool g(int n)
{
return (n%3 == 0);
}

მაშინ კოდი
k = my_search_if(v, g);
if(k != v.size())
cout << "multiple of 3 found at index " << k << endl;
else
cout << "Not found!" << endl

;დაბეჭდავს v ვექტორში მარცნიდან პირველივე სამის ჯერად რიცხვს, თუ ასეთი არის, ან


დაბეჭდავს გზავნილს რომ ასეთი რიცხვები ვერ მოიძებნა.

ამოცანა 2:
შექმენით იტერაციული ფუნქცია ვექტორში ინდექსების [l,r) დიაპაზონში ელემენტების
ჯამის განსაზღვრისთვის. შემდეგ ეს ფუნქცია გარდაქმენით ეკვივალენტურ რეკურსიულ
ფუნქციად.

ამოხსნა: ყალიბიანი ფუნქციების შექმნა ბევრი ფაქტორის გათვალისწინებას საჭიროებს. ამ


მაგალითში, არსებითია ფუნქციას გადავაწოდოთ საწყისი მნიშვნელობა, რომლიდანაც დაიწყებს
ელემენტების ჯამის დაგროვებას. გადაწოდების ძირითადი მიზანი იმაში მდგომარეობს, რომ
ფუნქციას შეექმნას იგივე ტიპის ლოკალური ცვლადი ჯამისთვის, რა ტიპისაცაა ვექტორი.
template<typename T>
T mySumIterative(const vector<T> &v, int l, int r, T initial_value)
{
while(l < r )
{
initial_value += v[l];
++l;
}
return initial_value;
}
დავწეროთ ისეთი იტერაციული კოდი, რომ ფუნქციის ტანი მხოლოდ ერთი while(true)
შეტყობინებისგან შედგებოდეს:
template<typename T>
T mySumIterative1(const vector<T> &v, int l, int r, T initial_value)
{
while( true )
{
if(l >= r)
return initial_value;
initial_value += v[l];
++l;
Page 2 of 4
}
}

ახლა, while შეტყობინება შევცვალოთ ფუნქციის გამოძახებით, ოღონდ თუ while იყო


პირველი შესრულებადი შეტყობინება, ფუნქციის გამოძახება გახდება ბოლო შესრულებადი.
ოღონდ ახლა
template<typename T>
T mySumRecursive(const vector<T> &v, int l, int r, T initial_value)
{
if(l >= r)
return initial_value;
initial_value += v[l];
++l;
return mySumRecursive(v,l,r,initial_value);
}
პროგრამა დრაივერს შესაძლოა ჰქონდეს სახე:
int main()
{

int mas[] = {11,3,26,7,11,213,7,123,-31};


int dim(sizeof(mas)/sizeof(int));
vector<int> v(&mas[0],&mas[dim]);

int init(0);
int sum = mySumRecursive(v, 0,5,init);
cout << "summ od ints = " << sum << endl;
cout << "initial_value = " << init << endl;

double masD[] = {18.2, 3.09, 26.21, 7.54, 11.1, 21.3,7.5, 123.54, -3.14};
int dimD(sizeof(masD)/sizeof(double));
vector<double> v1(&masD[0],&masD[dimD]);

double init1( 0.0);


double sum1= mySumRecursive(v1, 0, 2, init1);
cout << "summ of doubles = " << sum1 << endl;

return 0;
}

ამოცანები დამოუკიდებელი მუშაობისთვის:


1. განხილულ ამოცანაში, ძებნის ფუნქცია გადააკეთეთ ისე, რომ მათ მოძებნოს საძიებელი
თვისების მქონე ელემენტი არა მთელ ვექტორში, არამედ მის ფრაგმენტში, ინდექსების
დიაპაზონით [l,r), ანუ პირველი ინდექსია l (ელ), ხოლო პირველი დიაპაზონიდან
გასული ინდექსი არის r(ერ).
2. შექმენით ფუნქცია, რომელიც დაბეჭდავს სხვადასხვა ტიპის ვექტორის ელემენტებს m
სვეტად. ვექტორის სახელი და სვეტების რაოდენობა უნდა იყოს ფუნქციის პარამეტრები.
3. შექმენით ფუნქცია, რომელიც m სვეტად დაბეჭდავს სხვადასხვა ტიპის ვექტორის ისეთ
ელემენტებს, რომელიბიც აკმაყოფილებენ გარკვეულ თვისებას. ვექტორის სახელი, სვეტების
რაოდენობა და თვისება უნდა იყოს ფუნქციის პარამეტრები.
4. შექმენით ფუნქცია, რომელიც შეავსებს სხვადასხვა ტიპის ვექტორებს კლავიატურიდან ან
ფაილიდან.
5. მოცემულია ნამდვილი ან მთელი რიცხვების ვექტორი. დაწერეთ ფუნქცია, რომელიც
რეკურსიულად დაითვლის ამ ვექტორში ინდექსების დიაპაზონში [l,r) ელემენტების
 კვადრატების ჯამს;
 შებრუნებული ელემენტების ჯამს (ვიგულისხმოთ რომ არანულოვანებია).

Page 3 of 4
*
6 . ამოცანა 1-ში კოდი იგივე რჩება, თუ თუ მოვინდომებთ დეკის გამოყენებას, როგორ
განვაზოგადოთ ალგორითმი ისე, რომ მან იმუშაოს ორივე აღნიშნულ კონტეინერთან?

Page 4 of 4

You might also like