String.split not counting the last empty elements - regex

Look at the following 2 examples. How to make sure the 2nd one prints 4 as well?
String s="a|b|c|d"
println(s.split("\\|").length)
//prints 4
s="a|b||"​​​​​​​​​​​​
println(s.split("\\|").length)​
//prints 2

To keep the empty token, use split with limit = -1
println(s.split("\\|", -1).length)​

Split wont allow you to have null values when you iterate. So the following code will work.
int counter = 0;
for(int i = 0 ; i < s.length();i++)
{
if(s.charAt(i) == '|')
{
counter++;
}
}
System.out.println(counter);

Related

Remove adjacent duplicates

Expected output is "ca" but I'm getting "aca". I have dry ran it, but do not understood why it is doing so. Please, can anyone help me in solving this?
#include<bits/stdc++.h>
using namespace std;
int main()
{
string a = "abbaca";
int i = 0;
while(i < a.size()){
if(a[i] == a[i+1]){
a.erase(i, i+1);
i = 0;
}
else{
i++;
}
}
cout << a;
return 0;
}
a.erase(i, i+1) is wrong.
The string::erase() method takes a starting index and a count, not a pair of indexes denoting a range, as you are thinking.
When removing the duplicate bs, i is 1, and you erase i+1=2 chars, thus "abbaca" becomes "aaca", which is correct. But then, the loop starts over, and when removing the duplicate as, i is 0, so you erase i+1=1 char, thus "aaca" becomes "aca", which is wrong.
You want to remove exact 2 chars each time, so use a.erase(i, 2) instead.
Online Demo
The function 'erase()' erases a part of the string content, shortening the length of the string.The second parameter in the erase function is the count, it means how many characters you want it to remove. If you want 'ca' as expected output you should mention 2 as count of characters to be removed. In the first case it becomes 2 so bb is removed but for 'aa' the count becomes as 1 so 'aca' is the output.
Below is the code for output 'ca', change this erase statement as shown:
if(a[i]==a[i+1]){
a.erase(i,2);
i=0;
}
keep the rest as same

my run-length encoding doesn't work with big numbers

I have a assingment were I need to code and decode txt files, for example: hello how are you? has to be coded as hel2o how are you? and aaaaaaaaaajkle as a10jkle.
while ( ! invoer.eof ( ) ) {
if (kar >= '0' && kar <= '9') {
counter = kar-48;
while (counter > 1){
uitvoer.put(vorigeKar);
counter--;
}
}else if (kar == '/'){
kar = invoer.get();
uitvoer.put(kar);
}else{
uitvoer.put(kar);
}
vorigeKar = kar;
kar = invoer.get ( );
}
but the problem I have is if need to decode a12bhr, the answer is aaaaaaaaaaaabhr but I can't seem to get the 12 as number without problems, I also can't use any strings or array's.
c++
I believe that you are making following mistake: imagine you give a32, then you read the character a and save it as vorigeKar (previous character, I am , Flemish so I understand Dutch :-) ).
Then you read 3, you understand that it is a number and you repeat vorigeKar three times, which leads to aaa. Then you read 2 and repeat vorigeKar two times, leading to aaaaa (five times, five equals 3 + 2).
You need to learn how to keep on reading numeric characters, and translate them into complete numbers (like 32, or 12 in your case).
Like #Dominique said in his answers, You're doing it wrong.
Let me tell you my logic, you can try it.
Pesudo Code + Logic:
Store word as a char array or string, so that it'll be easy to print at last
Loop{
Read - a //check if it's number by subtracting from '0'
Read - 1 //check if number = true. Store it in int res[] = res*10 + 1
//Also store the previous index in an index array(ie) index of char 'a' if you encounter a number first time.
Read - 2 //check if number = true. Store it in res = res*10 + 2
Read - b , h and so on till "space" character
If you encounter another number, then store it's previous character's index in index array and then store the number in a res[] array.
Now using index array you can get the index of your repeating character to be printed and print it for it's corresponding times which we have stored in the result array.
This goes for the second, third...etc:- numbers in your word till the end of the word
}
First, even though you say you can't use strings, you still need to know the basic principle behind how to turn a stream of digit characters into an integer.
Assuming the number is positive, here is a simple function that turns a series of digits into a number:
#include <iostream>
#include <cctype>
int runningTotal(char ch, int lastNum)
{
return lastNum * 10 + (ch -'0');
}
int main()
{
// As a test
char s[] = "a123b23cd1/";
int totalNumber = 0;
for (size_t i = 0; s[i] != '/'; ++i)
{
char digit = s[i]; // This is the character "read from the file"
if ( isdigit( digit) )
totalNumber = runningTotal(digit, totalNumber);
else
{
if ( totalNumber > 0 )
std::cout << totalNumber << "\n";
totalNumber = 0;
}
}
std::cout << totalNumber;
}
Output:
123
23
1
So what was done? The character array is the "file". I then loop for each character, building up the number. The runningTotal is a function that builds the integer from each digit character encountered. When a non-digit is found, we output that number and start the total from 0 again.
The code does not save the letter to "multiply" -- I leave that to you as homework. But the code above illustrates how to take digits and create the number from them. For using a file, you would simply replace the for loop with the reading of each character from the file.

count consecutive 1's in binary

I am writing code in Hackerrank. And recently the problem said, convert decimal to base 2 and then count the max consecutive 1's in the binary number. And first I come with following solution. It works fine. But I do not understand the counting part of it, even though I wrote it.
The code is
int main(){
int n,ind=0, count=0, mmax=0;
char bin[100];
cin >> n;
while(n){
if(n%2==0) {
bin[ind]='0';
n = n / 2;
ind = ind + 1;
}
else if(n%2==1) {
bin[ind]='1';
n = n / 2;
ind = ind + 1;
}
}
for(int i=0; i<=(ind-1); i++){
if(bin[i] == '1' && bin[i+1] == '1'){
count++;
if(mmax < count)
mmax = count;
}
else
count=0;
}
cout << mmax + 1 << endl;
return 0;
}
In the above code, I guess that variable mmax will give me the max consecutive number of 1's but it gives me value that has (max consecutive - 1), So I just wrote like that and submitted the code. But I am curious about. why it is working that way. I am little bit of confused the way that code works like this.
Thanks
Lets say you have this binary sequence:
11110
Your code will compare starting from the first and second:
|11|110 1 && 1 -> max = 1
1|11|10 1 && 1 -> max = 2
11|11|0 1 && 1 -> max = 3
111|10| 1 && 0 -> max = 3
you can see, that although there are 4 1's you only do 3 comparisons, so your max will always be -1 of the actual max. You can fix this by adding mmax += 1 after your for loop.
Just a little bit of trace using small example will show why.
First, lets say there is only 1 '1' in your array.
Since you require both the current position and your next position to be '1', you will always get 0 for this case.
Let's say I have "11111". At the first '1', since next position is also '1', you increment count once. This repeats until 4th '1' and you increment your count 4 times in total so far. When you reach 5th '1', your next position is not '1', thus your count stops at 4.
In general, your method is like counting gaps between fingers, given 5 fingers, you get 4 gaps.
Side note: your code will fail for the case when there is no '1' in your array.

Compare part of the string

Okay so here is what I'm trying to accomplish.
First of all below table is just an example of what I created, in my assignment I'm not suppose to know any of these. Which means I don't know what they will pass and what is the length of each string.
I'm trying to accomplish one task is to get to be able to compare part of the string
//In Array `phrase` // in array `word`
"Backdoor", 0 "mark" 3 (matches "Market")
"DVD", 1 "of" 2 (matches "Get off")
"Get off", 2 "" -1 (no match)
"Market", 3 "VD" 1 (matches "DVD")
So as you can see from the above codes from the left hand side is the set of array which I store them in my class and they have upto 10 words
Here is the class definition.
class data
{
char phrase[10][40];
public:
int match(const char word[ ]);
};
so I'm using member function to access this private data.
int data::match(const char word[ ])
{
int n,
const int wordLength = strlen(word);
for (n=0 ; n <= 10; n++)
{
if (strncmp (phrase[n],word,wordLength) == 0)
{
return n;
}
}
return -1;
}
The above code that I'm trying to make it work is that it should match and and return if it found the match by returning the index n if not found should always return -1.
What happen now is always return 10.
You're almost there but your code is incomplete so I''m shootin in the dark on a few things.
You may have one too many variables representing an index. Unless n and i are different you should only use one. Also try to use more descriptive names, pos seems to represent the length of the text you are searching.
for (n=0 ; n <= searchLength ; n++)
Since the length of word never changes you don't need to call strlen every time. Create a variable to store the length in before the for loop.
const int wordLength = strlen(word);
I'm assuming the text you are searching is stored in a char array. This means you'll need to pass a pointer to the first element stored at n.
if (strncmp (&phrase[n],word,wordLength) == 0)
In the end you have something that looks like the following:
char word[256] = "there";
char phrase[256] = "hello there hippie!";
const int wordLength = strlen(word);
const int searchLength = strlen(phrase);
for (int n = 0; n <= searchLength; n++)
{
// or phrase + n
if (strncmp(&phrase[n], word, wordLength) == 0)
{
return n;
}
}
return -1;
Note: The final example is now complete to the point of returning a match.
I'm puzzled about your problem. There are some cases unclear. For eaxmple abcdefg --- abcde Match "abcde"? how many words match? any other examples, abcdefg --- dcb Match "c"?and abcdefg --- aoodeoofoo Match "a" or "adef"? if you want to find the first matched word, it's OK and very simple. But if you are to find the longest and discontinuous string, it is a big question. I think you should have a research about LCS problem (Longest Common Subsequence)

comparing bits (one position at a time)

Initially I have user input decimal numbers (0 - 15), and I will turn that into binary numbers.
Say these numbers are written into a text file, as shown in the picture. These numbers are arranged by the numbers of 1's. The dash - is used to separate different groups of 1.
I have to read this file, and compare strings of one group with the all the strings in the group below, i.e., Group 1 with all the strings in group 2, and group 2 - group 3.
The deal is that, only one column of 0 / 1 difference is allowed, and that column is replaced by letter t. If more than one column of difference is encountered, write none.
So say group 2, 0001 with group 3, 0011, only the second column is different. however, 0010 and 0101 are two columns of difference.
The result will be written into another file.....
At the moment, when I am reading these strings, I am using vector string. I came across bitset. What is important is that I have to access the character one at a time, meaning I have break the vector string into vector char. But it seems like there could be easier way to do it.
I even thought about a hash table - linked-list. Having group 1 assigned to H[0]. Each comparison is done as H[current-group] with H[current_group+1]. But beyond the first comparison (comparing 1's and 0's), the comparison beyond that will not work under this hash-linked way. So I gave up on that.
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <algorithm>
#include <iterator>
using namespace std;
int main() {
ifstream inFile("a.txt");
vector<string> svec;
copy(istream_iterator<string>(inFile), istream_iterator<string>(), back_inserter(svec));
copy(svec.begin(), svec.end(), ostream_iterator<string>(cout,"\n"));
for(int i = 0; i < svec.size(); i++)
{
cout << svec[i] << " ";
}
inFile.close();
return 0;
}
This is the sample code of writing it into a file....but like I said, the whole deal of vector seems impractical in my case....
Any help is appreciated. thanks
I don't understand your code snippet -- it looks like all it does is read in the input file into a vector of strings, which will then contain each whitespace-delimited word in a separate string, then write it back out in 2 different ways (once with words separated by \n, once with them separated by spaces).
It seems the main problem you're having is with reading and interpreting the file itself, as opposed to doing the necessary calculations -- right? That's what I hope this answer will help you with.
I think the line structure of the file is important -- right? In that case you would be better off using the global getline() function in the <string> header, which reads an entire line (rather than a whitespace-delimited word) into a string. (Admittedly that function is pretty well-hidden!) Also you don't actually need to read all the lines into a vector, and then process them -- it's more efficient and actually easier to distill them down to numbers or bitsets as you go:
vector<unsigned> last, curr; // An unsigned can comfortably hold 0-15
ifstream inf("a.txt");
while (true) {
string line;
getline(inf, line); // This is the group header: ignore it
while (getline(inf, line)) {
if (line == "-") {
break;
}
// This line contains a binary string: turn it into a number
// We ignore all characters that are not binary digits
unsigned val = 0;
for (int i = 0; i < line.size(); ++i) {
if (line[i] == '0' || line[i] == '1') {
val = (val << 1) + line[i] - '0';
}
}
curr.push_back(val);
}
// Either we reached EOF, or we saw a "-". Either way, compare
// the last 2 groups.
compare_them_somehow(curr, last); // Not doing everything for you ;)
last = curr; // Using swap() would be more efficient, but who cares
curr.clear();
if (inf) {
break; // Either the disk exploded, or we reached EOF, so we're done.
}
}
Perhaps I've misunderstood your goal, but strings are amenable to array member comparison:
string first = "001111";
string next = "110111";
int sizeFromTesting = 5;
int columnsOfDifference = 0;
for ( int UU = sizeFromTesting; UU >=0; UU-- )
{
if ( first[ UU ] != next[ UU ] )
columnsOfDifference++;
}
cout << columnsOfDifference;
cin.ignore( 99, '\n' );
return 0;
Substitute file streams and bound protection where appropriate.
Not applicable, but to literally bitwise compare variables, & both using a mask for each digit (000010 for second digit).
If or = 0, they match: both are 0. If they or = 1 and & = 1, that digit is 1 for both. Otherwise they differ. Repeat for all the bits and all the numbers in the group.
in vb.net
'group_0 with group_1
If (group_0_count > 0 AndAlso group_1_count > 0) Then
Dim result = ""
Dim index As Integer = 0
Dim g As Integer = 0
Dim h As Integer = 0
Dim i As Integer = 0
For g = 0 To group_0_count - 1
For h = 0 To group_1_count - 1
result = ""
index = 0
For i = 0 To 3
If group_1_0.Items(g).ToString.Chars(i) <> group_1_1.Items(h).ToString.Chars(i) Then
result &= "-"
index = index + 1
Else
result &= group_1_0.Items(g).ToString.Chars(i)
End If
Next
Next
Next
End If
Read it in as an integer, then all you should need is comparisons with bitshifts and bit masks.