STL Functions vector processing

I want to use an STL function on a vector of strings. The final objective is to get the index of the string which is least letter different from the next.

for example if my vector contains {"One", "one", "Two"}

different betwen first two string is one letter so 1
different between second and third is all so 3 .

Now the function must return 1(the position of the string with least difference)

But wait... no for ,while loops.

I am thinking abt accumulate etc... but nothing fits the scenario or I dont know how to fit this.
Using adjacent_find... am I right?
Last edited on
You could use adjacent_difference (from <numeric>) with a binary op to compare two strings. Then use min_element (from <algorithm>) to find the position of the minimum.

Alternatively, you can use recursion to avoid explicit loops.

Either way you will need a function to count the differences between two strings.


Somewhere along the line you will have to decide whether "position" starts from 0 or 1.
One approach could be (pseudo code):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
found_index <- 0
found_difference <- max_num

for i <- 0 to all elements in vector - 1 // Not: -1
{
  max / min <- word[i] length, word[i + 1] length
  current_difference <- max - min

  for j <- 0 to min
  {
    if word[i][j] != word[i + 1][j]
      ++current_difference
  }

  if current_difference < found_difference
    found_index <- current_index
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#include <iostream>
#include <string>
#include <vector>
#include <limits>
using namespace std;


int stringDiffer( const string &str1, const string &str2 )
{
   if      ( str1.empty() ) return str2.length();
   else if ( str2.empty() ) return str1.length();
   else                     return ( str1[0] != str2[0] ) + stringDiffer( str1.substr( 1 ), str2.substr( 1 ) );
}


void minDif( const vector<string> &test, int a, int b, int &minPos, int &minVal )
{
   int d = stringDiffer( test[a], test[a+1] );
   if ( d < minVal )
   {
      minPos = a;
      minVal = d;
   }
   if ( a < b ) minDif( test, a + 1, b, minPos, minVal );
}


int main()
{
   bool oneIndexed = true;
   vector<string> test = { "One", "one", "Two" };

   int minPos = 0, minVal = numeric_limits<int>::max();
   minDif( test, 0, test.size() - 2, minPos, minVal );
   cout << "Min difference " << minVal << " at position " << minPos + oneIndexed << '\n';
}




Turned out to be frustratingly difficult with std::adjacent_difference(). For some reason it doesn't seem to like different types of input and output iterators. Perhaps it's only geared up to numerical quantities.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include <iostream>
#include <string>
#include <vector>
#include <limits>
#include <numeric>
#include <algorithm>
using namespace std;


int stringDiffer( const string &str1, const string &str2 )
{
   if      ( str1.empty() ) return str2.length();
   else if ( str2.empty() ) return str1.length();
   else                     return ( str1[0] != str2[0] ) + stringDiffer( str1.substr( 1 ), str2.substr( 1 ) );
}


int minDifPos( const vector<string> &test )
{
   vector<string> A( test.size() );
   adjacent_difference( test.begin(), test.end(), A.begin(), []( string a, string b ){ return to_string( stringDiffer( a, b ) ); } );
   return min_element( A.begin() + 1, A.end(), []( string a, string b ){ return stoi( a ) < stoi( b ); } ) - ( A.begin() + 1 );
}


int main()
{
   bool oneIndexed = true;
   vector<string> test = { "One", "one", "Two" };

   cout << minDifPos( test ) + oneIndexed << '\n';
}

Last edited on
I used help from the answers... this is how I did

This is my code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
int stringDiffer( const string &x, const string &y )
{
    int difference;
   if      ( x.empty() ) difference= y.length();
   else if ( y.empty() ) difference= x.length();
   else                     difference= ( x[0] != y[0] ) + stringDiffer( x.substr( 1 ), y.substr( 1 ) );
   return difference ;
}


int distanceFinder(const std::vector<string> &v, int n)
{
    
    auto i1 = std::adjacent_find(v.begin(), v.end(), [=](string x,string y)
    {
        int difference;
                           
        difference=  stringDiffer( x, y );
        
        return (difference<=n);
    }
    
    
    );
    int returnValue;
 
    if (i1 == v.end()) {
        returnValue=-1;
    } else {
        returnValue= std::distance(v.begin(), i1) ;
    }
    return returnValue;
    
    
}

int main() {
 
 
    
    const std::vector<std::string> more_words { 
  "this is a sentence.",
  "this is also words ",
  "another line in one",
  "another LINE_in one",
  "stuff words in open",
  "stuff words in OPEN",
  "whitespace\n\tagain  ",
};
    
std::cout<<distanceFinder(more_words, 5)<<std::endl;   
std::cout<<distanceFinder(more_words, 4)<<std::endl;
std::cout<<distanceFinder(more_words, 0)<<std::endl;
//std::cout<<distanceFinder(more_words, 0)<<std::endl;
    return 0;
}

I was using the set_intersect function instead of the stringDiffer but for some reason...
the code gave me wrong intersect... any guess what I missed to understand. I was expecting 14 characters to be same including the spaces.

This is my code:
1
2
3
4
5
6
7
8
   std::string s;
   std::string x="another line in one";
   std::noskipws;
   std::string y="another LINE_in one";
   std::set_intersection(x.begin(), x.end(),
                      y.begin(), y.end(),
                      std::inserter(s, s.begin()));
                      std::cout<<s;

Thanks
Last edited on
I used help from the answers...

Could you
PLEASE learn to use code tags, they make reading and commenting on source code MUCH easier.

http://www.cplusplus.com/articles/jEywvCM9/
http://www.cplusplus.com/articles/z13hAqkS/

HINT: you can edit your post and add code tags.

Some formatting & indentation would not hurt either
set_intersection assumes that the specified data range is sorted.

Constructs a sorted range beginning in the location pointed by result with the set intersection of the two sorted ranges [first1,last1) and [first2,last2).


http://www.cplusplus.com/reference/algorithm/set_intersection/
you can do almost anything by hiding the loop in std::transform too. It appears to be mostly nothing more than an empty loop with a callback to whatever you tell it to do inside the loop.
But wait... no for ,while loops.

Is that "thou shalt not write a loop in your own code"
or
"you are not allowed to use anything that is implemented* with loops"?

*Although we don't know how libraries are implemented, if they could be, then assume they are?


And as cherry on top, is do..while a while-loop or separate loop?
STL Functions vector processing

std::for_each https://en.cppreference.com/w/cpp/algorithm/for_each

or

std::ranges::for_each https://en.cppreference.com/w/cpp/algorithm/ranges/for_each

But wait... no for ,while loops.

The <algorithm> library might have the functions using some variant of a for loop, but not guaranteed.

You want to transverse a C++ container will require some form of a loop, a for or while/do-while are more efficient depending on the immediate need.

A goto loop is possible, but that is a real smelly bit of code.
When there is a need to use std functions then (using my algorithm) I would think of std::sort(...)
Topic archived. No new replies allowed.