The question is simple. I'm looking for an easy and efficient way of joining an array of strings (or arrays of any other type, for that matter, since strings are an alias for char[]), with an optional separator.
In JavaScript, this functionality would already exist with the join method. Being new to D, I failed to find something as easy as that in the standard library. It would be too bad if I had to implement a utility function myself.
So instead of something like this:
string merge (const string arr[] , const string separator) {
if (arr.length == 0) return "";
string r = arr[0];
for (int i = 1 ; i < arr.length ; i++) {
r ~= separator ~ arr[i];
}
return r;
}
What would an experienced D programmer do?
I'm not a D programmer, but I'll take a crack at it, the library reference has a join method.
From the docs:
const string[] arr = ["apple", "banana"];
assert(arr.join(",") == "apple,banana");
assert(arr.join() == "applebanana");
See also std.algorithm.joiner for a version that is lazy and doesn't allocate any memory.
Related
I'm trying to alphabetize words in a vector of strings and my program is distinguishing between upper and lowercase letters, so uppercase words always appear first in the sorted list. I can think of potentially really cumbersome ways to make sure the upper case words go in their place, but is there a simple way to do this?
Here is my code:
for (int i = 0; i < str.size(); i++)
{
for (int j = 0; j < str.size(); j++)
{
if (str.at(i) > str.at(j))
{
temp = str.at(j);
str.at(j) = str.at(i);
str.at(i) = temp;
}
}
}
Also, this is for a programming assignment, so I am not allowed to use built in C++ functions to do this and I have to use a vector.
The trick to solving this is to write a replacement for this line
if (str.at(i) > str.at(j))
that performs case-insensitive comparison. Start by writing a signature for it:
bool greaterThanIgnoreCase(const string& left, const string& right) {
...
}
Now you can replace your if condition with a call to this new function:
if (greaterThanIgnoreCase(str.at(i), str.at(j)))
Finally, you need to provide an implementation of greaterThanIgnoreCase function. This is the core of the problem, so you would need to do it yourself. The trick to it is using toupper or tolower function on each character of strings left and right, and compare them one character at a time. If you run out of characters in one of the strings, the one with some characters remaining should be considered greater.
The only thing you need to do is to compare lowercased characters. If you are not allowed to use any built-in functions, you can do it manually.
Since lowercase characters are located in ASCII table starting from 97, and uppercase - starting from 65, you can simply add 32 to the uppercase char to get its lowercase equivalent.
char lowerCase(char c)
{
if (c >= 'A' && c <= 'Z') // if char is uppercase
return (char)(c + 32); // return its lowercase equivalent
else
return c;
}
Then, you can do the following in your if condition:
if (lowerCase(str.at(i)) > lowerCase(str.at(j)))
Note that you shouldn use lowerCase only when you compare, but not when you assign.
Here is the working IDEOne demo.
If you have a vector of strings then you could/should use the STL library, which offers sort or stable_sort for a given comparison function (that can be a simple lambda expression, functor, function,...).
Update: You're not allowed to use built-in types except vector.
In this case you can develop easily a replicate of what STL does.
Define a sort function that receives a comparator (for a vector of strings).
This question already has answers here:
How to strip all non alphanumeric characters from a string in c++?
(12 answers)
Closed 6 years ago.
I'm trying to remove all non alphabet characters from an inputed string in c++ and don't know how to. I know it probably involves ascii numbers because that's what we're learning about. I can't figure out how to remove them. We only learned up to loops and haven't started arrays yet. Not sure what to do.
If the string is Hello 1234 World&*
It would print HelloWorld
If you use std::string and STL, you can:
string s("Hello 1234 World&*");
s.erase(remove_if(s.begin(), s.end(), [](char c) { return !isalpha(c); } ), s.end());
http://ideone.com/OIsJmb
Note: If you want to be able to handle strings holding text in just about any language except English, or where programs use a locale other than the default, you can use isalpha(std::locale).
PS: If you use a c-style string such as char *, you can convert it to std::string by its constructor, and convert back by its member function c_str().
If you're working with C-style strings (e.g. char* str = "foobar") then you can't "remove" characters from a string trivially (as a string is just a sequence of characters stored sequentially in memory - removing a character means copying bytes forward to fill the empty space used by the deleted character.
You'd have to allocate space for a new string and copy characters into it as-needed. The problem is, you have to allocate memory before you fill it, so you'd over-allocate memory unless you do an initial pass to get a count of the number of characters remaining in the string.
Like so:
void BlatentlyObviousHomeworkExercise() {
char* str = "someString";
size_t strLength = ... // how `strLength` is set depends on how `str` gets its value, if it's a literal then using the `sizeof` operator is fine, otherwise use `strlen` (assuming it's a null-terminated string).
size_t finalLength = 0;
for(size_t i = 0; i < strLength; i++ ) {
char c = str[i]; // get the ith element of the `str` array.
if( IsAlphabetical(c) ) finalLength++;
}
char* filteredString = new char[ finalLength + 1 ]; // note I use `new[]` instead of `malloc` as this is C++, not C. Use the right idioms :) The +1 is for the null-terminator.
size_t filteredStringI = 0;
for(size_t i = 0; i < strLength; i++ ) {
char c = str[i];
if( IsAlphabetical(c) ) filteredString[ filteredStringI++ ] = c;
}
filteredString[ filteredStringI ] = '\0'; // set the null terminator
}
bool IsAlphabet(char c) { // `IsAlphabet` rather than `IsNonAlphabet` to avoid negatives in function names/behaviors for simplicity
return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z');
}
I do not want to spoil the solution so I will not type out the code, only describe the solution. For your problem think of iterating through your string. Start with that. Then you need to decide if the currently selected character is part of the alphabet or not. You can do this numerous different ways. Checking ASCII values? Comparing against a string of the alphabet? Once you decide if it is a letter, then you need to rebuild the new string with that letter plus the valid letters before and after that you found or will find. Finally you need to display your new string.
If you look at an ascii table, you can see that A-Z is between 65-90 and a-z is between 97-122.
So, assuming that you only need to remove those characters (not accentuated), and not other characters from other languages for example, not represented in ascii, all you would need to do is loop the string, verify if each char is in these values and remove it.
1. vector<string> cmdv=explode(" ","i am a string");
2. std::string arg;
3. char * args[10];
4. for (i = 0; i < cmdv.size(); i++) {
5. arg = std::string(cmdv[i]);
6. if (cmdv[i][0] == '"') {
7. //do some thing
8. }
9. args[i] = arg.c_str();;
10. }
11. args[i]='\0';
I expected the contents of args array {"i","am","a","string"} but args array is {"am","a","string","string"}
on debug i found that at line 6 in if clause when cmdv[i][0] is compared with '"', args[i-1] is being replaced with contents of arg. I got baffled!
there is no problem with explode function. Its working good.
This is a problem :-
args[i] = arg.c_str();
The pointer returned by this is only valid while arg contains it's value and you alter arg each time through your loop. If you want to store a C style pointer to the string you'll need to make a copy of it, maybe something like :-
args[i] = strdup(arg.c_str());
But remember to free it. Plus there is probably a better way to achive what you want than using C style strings anyway
For example :
String is : abcd
shortest palindrome is abcdcba is the solution
longer palindrome can be : abcddcba
another example:
String : aaaab
shortest palindrome is aaaabaaaa
longer palindrome can be aaaaabbaaaa
Restrictions : you can only add characters in the end.
Just append the reverse of initial substrings of the string, from shortest to longest, to the string until you have a palindrome. e.g., for "acbab", try appending "a" which yields "acbaba", which is not a palindrome, then try appending "ac" reversed, yielding "acbabca" which is a palindrome.
Update: Note that you don't have to actually do the append. You know that the substring matches since you just reversed it. So all you have to do is check whether the remainder of the string is a palindrome, and if so append the reverse of the substring. Which is what Ptival wrote symbolically, so he should probably get the credit for the answer. Example: for "acbab", find the longest suffix that is a palindrome; that is "bab". Then append the remainder, "ac", in reverse: ac bab ca.
My guess for the logic:
Say you string is [a1...an] (list of characters a1 to an)
Find the smallest i such that [ai...an] is a palindrome.
The smallest palindrome is [a1 ... a(i-1)] ++ [ai ... an] ++ [a(i-1) ... a1]
where ++ denotes string concatenation.
Some pseudo code, to leave at least a bit of work on you:
def shortPalindrome(s):
for i in range(len(s)):
pal = s + reverse(s[0:i])
if isPalindrome(pal):
return pal
error()
Python code, should be easy to convert to C:
for i in range(1, len(a)):
if a[i:] == a[i:][::-1]:
break
print a + a[0:i][::-1]
I was also asked the same question recently, and here is what I wrote for my interview:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int isPalin ( char *str ) {
int i, len=strlen(str);
for (i=0; i<len/2; ++i)
if (str[i]!=str[len-i-1])
break;
return i==len/2;
}
int main(int argc, char *argv[]) {
if (argc!=2)
puts("Usage: small_palin <string>");
else {
char *str = argv[1];
int i=0, j, len=strlen(str);
while ( !isPalin(str+i) )
++i;
char *palin = malloc(len+1+i);
*(palin+len+1+i) = '\0';
strcpy(palin,str);
for (i=i-1, j=0; i>=0; --i, ++j)
*(palin+len+j) = str[i];
puts(palin);
}
return 0;
}
I feel that the program would have been more structured had I written an strrev() function and checked palindrome using strcmp(). This would enable me to reverse the starting characters of the source string and directly copy it using strcpy().
The reson why I went with this solution is that before this question I was asked to check for palindrome and I already had that isPalin() in paper. Kind of felt using existing code would be better !!
From the examples you shown looks like the longest palindrome is the original string concatenated with its reverse, and the shortest is the original string concatenated with its reverse except for the first character. But I'm pretty sure you want something more complex. Perhaps you can give better examples?
if string is made of k chars, I think you should add to this string the reversed (k-1) chars...
Below is my answer for another case: shortest palindrome by attaching characters to the front. So your task is to understand the algorithm and modify it appropriately.
Basically, it states that from a string s find the shortest palindrome by adding some characters to the front of s.
If you have never tried to solve this problem, I suggest that you solve it, and it will help you improve your problem solving skill.
After solving it, I kept looking for better solutions. I stumbled upon another programmer's solution. It is in python, and really neat. It is really interesting, but later I found out it was wrong.
class Solution:
# #param {string} s
# #return {string}
def shortestPalindrome(self, s):
A=s+s[::-1]
cont=[0]
for i in range(1,len(A)):
index=cont[i-1]
while(index>0 and A[index]!=A[i]):
index=cont[index-1]
cont.append(index+(1 if A[index]==A[i] else 0))
print cont[-1]
return s[cont[-1]:][::-1]+s
I myself looked at the Solution and saw it's interesting idea. At first, the algorithm concatenates the string and its reversed version. Then the following steps are similar to the steps for building KMP-table (or failure function) using in KMP algorithm. Why does this procedure work?
If you know KMP text searching algorithm, you will know its "lookup table" and steps to build it. Right now, I just show one important use of the table: it can show you the longest prefix of a string s that is also suffix of s (but not s itself). For example, "abcdabc" has the longest prefix which is also a suffix: "abc" (not "abcdabc" since this is the entire string!!!). To make it fun, we call this prefix is "happy substring" of s. So the happy substring of "aaaaaaaaaa" (10 a's ) is "aaaaaaaaa" (9 a's).
Now we go back and see how finding happy sub string of s can help solve the shortest palindrome problem.
Suppose that q is the shortest string added to the front of s to make the string qs is a palindrome. We can see that obviously length(q) < length(s) since ss is also a palindrome. Since qs is a palindrome, qs must end with q, or s = p+q where p is a sub string of s. Easily we see that p is also a palindrome. Therefore, in order to have shortest qs, q needs to be shortest. In turn, p is the longest palindromic sub string of s.
We call s' and q' are the reversed strings of s and q respectively. We see that s = pq, s' = q'p since p is a palindrome. So ss' = pqq'p . Now we need to find the longest p. Eureka! This also means that p is a happy sub string of the string ss'. That's how the above algorithm works!!!
However, after some thought, the above algorithm has some loophole. p is not a happy sub string of ss'! In fact, p is the longest prefix that is also a suffix of ss', but the prefix and suffix must not overlap each other. So let's make it more fun, we call "extremely happy sub string" of a string s is the longest sub string of s that is a prefix and also a suffix and this prefix and suffix must not overlap. On the other word, the "extremely happy sub string" of s must have length less than or equal half length of s.
So it turns out the "happy sub string" of ss' is not always "extremely happy sub string" of ss'. We can easily construct an example: s = "aabba". ss'="aabbaabbaa". The happy sub string of "aabbaabbaa" is "aabbaa", while the extremely happy sub string of "aabbaabbaa" is "aa". Bang!
Hence, the correct solution should be as following, based on the observation that length(p) <= length(ss')/2.
class Solution:
# #param {string} s
# #return {string}
def shortestPalindrome(self, s):
A=s+s[::-1]
cont=[0]
for i in range(1,len(A)):
index=cont[i-1]
while(index>0):
if(A[index]==A[i]):
if index < len(s):
break
index=cont[index-1]
cont.append(index+(1 if A[index]==A[i] else 0))
print cont[-1]
return s[cont[-1]:][::-1]+s
Hooray!
As you can see, algorithms are interesting!
The link to the article I wrote here
It looks like the solutions outlined here are O(N^2) (for each suffix X of the reversed string S, find if S + X is a palindrome).
I believe there is a linear, i.e O(N) solution for this problem. Consider the following statement: the only time where you would append less characters than S.Length - 1 is when the string already contains a partial palindrome, so it will be in the form of NNNNNPPPPPP, where PPPPP represent a palindrome. This means that if we can find the largest trailing palindrome, we can solve it linearly by concatenating the reverse of NNNNN to the end.
Finally, there exists a famous algorithm (Manacher, 1975) that finds the longest (and in fact, all) of the palindromes contained in a string (there is a good explanation here). It can be easily modified to return the longest trailing palidrome, thus giving a linear solution for this problem.
If anyone is interested, here is the full code for a mirror problem (append characters at the beginning):
using System.Text;
// Via http://articles.leetcode.com/2011/11/longest-palindromic-substring-part-ii.html
class Manacher
{
// Transform S into T.
// For example, S = "abba", T = "^#a#b#b#a#$".
// ^ and $ signs are sentinels appended to each end to avoid bounds checking
private static string PreProcess(string s)
{
StringBuilder builder = new StringBuilder();
int n = s.Length;
if (n == 0) return "^$";
builder.Append('^');
for (int i = 0; i < n; i++)
{
builder.Append('#');
builder.Append(s[i]);
}
builder.Append('#');
builder.Append('$');
return builder.ToString();
}
// Modified to return only the longest palindrome that *starts* the string
public static string LongestPalindrome(string s)
{
string T = PreProcess(s);
int n = T.Length;
int[] P = new int[n];
int C = 0, R = 0;
for (int i = 1; i < n - 1; i++)
{
int i_mirror = 2 * C - i; // equals to i' = C - (i-C)
P[i] = (R > i) ? Math.Min(R - i, P[i_mirror]) : 0;
// Attempt to expand palindrome centered at i
while (T[i + 1 + P[i]] == T[i - 1 - P[i]])
P[i]++;
// If palindrome centered at i expand past R,
// adjust center based on expanded palindrome.
if (i + P[i] > R)
{
C = i;
R = i + P[i];
}
}
// Find the maximum element in P.
int maxLen = 0;
int centerIndex = 0;
for (int i = 1; i < n - 1; i++)
{
if (P[i] > maxLen
&& i - 1 == P[i] /* the && part forces to only consider palindromes that start at the beginning*/)
{
maxLen = P[i];
centerIndex = i;
}
}
return s.Substring((centerIndex - 1 - maxLen) / 2, maxLen);
}
}
public class Solution {
public string Reverse(string s)
{
StringBuilder result = new StringBuilder();
for (int i = s.Length - 1; i >= 0; i--)
{
result.Append(s[i]);
}
return result.ToString();
}
public string ShortestPalindrome(string s)
{
string palindrome = Manacher.LongestPalindrome(s);
string part = s.Substring(palindrome.Length);
return Reverse(part) + palindrome + part;
}
}
using System;
using System.Collections.Generic;
using System.Linq;
public class Test
{
public static void shortPalindrome(string [] words){
List<string> container = new List<string>(); //List of Palindromes
foreach (string word in words )
{
char[] chararray = word.ToCharArray();
Array.Reverse(chararray);
string newText = new string(chararray);
if (word == newText) container.Add(word);
}
string shortPal=container.ElementAt(0);
for(int i=0; i<container.Count; i++)
{
if(container[i].Length < shortPal.Length){
shortPal = container[i];
}
}
Console.WriteLine(" The Shortest Palindrome is {0}",shortPal);
}
public static void Main()
{
string[] word = new string[5] {"noon", "racecar","redivider", "sun", "loss"};
shortPalindrome(word);
}
}
Shortest palindrome -
Reverse iterate from last positon + 1 to beginning
Push_back the elements
#include <iostream>
#include <string>
using namespace std ;
int main()
{
string str = "abcd" ;
string shortStr = str ;
for( string::reverse_iterator it = str.rbegin()+1; it != str.rend() ; ++it )
{
shortStr.push_back(*it) ;
}
cout << shortStr << "\n" ;
}
And longer palindrome can be any longer.
Ex: abcd
Longer Palindrome - abcddcba, abcdddcba, ...
How can i do a Bitwise OR on strings?
A:
10001
01010
------
11011
Why on strings?
The Bits can have length of 40-50.Maybe this could be problematic on int ?
Any Ideas ?
I would say std::bitset is more than enough for your situation, but for more flexibility you can use boost::dynamic_bitset. Here is an example on std::bitset:
const size_t N = 64;
string a_str = "10001", b_str = "01010";
bitset<N> a(a_str), b(b_str);
bitset<N> c = a | b;
cout << c;
You should take a look at the C++ std::bitset class, which does exactly what you want.
For each char:
char result = (a - '0') | (b - '0') + '0';
Where a and b are two chars with ascii character 0 or 1 in them.
Why not just use a vector of int values? Doesn't the bitset still use a byte per bit?
You can also use a vector of bool values, but this is also implementation specific.
Depending on whether you need storage efficiency or speed (or the utility of container methods that a couple of these approaches lack) you might profile to decide which approach to use.
This is similar to Andreas Brinck's answer, only it returns a full output string and can compare strings of different (arbitrary) lengths.
Example in C# (not near c++ compiler right now), but it should be simple to convert it to a language of your choice.
public static string BitwiseOr(string input1, string input2)
{
char[] inarr1 = (char[])input1.ToCharArray().Reverse().ToArray();
char[] inarr2 = (char[])input2.ToCharArray().Reverse().ToArray();
char[] outarr = new char[input1.Length > input2.Length ? input1.Length : input2.Length];
for (int i = 0; i < outarr.Length ; i++)
{
char c1 = i < input1.Length ? inarr1[i] : '0';
char c2 = i < input2.Length ? inarr2[i] : '0';
outarr[i] = (char)((c1 - '0') | (c2 - '0') + '0');
}
return new string((char[])outarr.Reverse().ToArray());
}
Of course this is only valid if you really need it to be in a string, if not you should (as suggested in other answers) use a vector or similar data type.