Related
This problem is an addition to the familiar stack question(https://leetcode.com/problems/minimum-add-to-make-parentheses-valid/) where we have to return the minimum number of additions to make the parentheses string valid. But that question consists of only '(' and ')'. What will happen if we extend that question to other types of parentheses like '[', ']', '{', '}'. I just came across this in a discussion among my friends and need help on how to approach.
For example: [[[{{}]]){)}) -> [[[{{}}]]] (){()}()
in this case answer is 5 additions to make it valid.
I couldn't come up with a proper approach. 2 approaches I considered are:
Similar to normal question, we push the opening types '(', '{', '[' to the stack as we browse through the string and if we find closing type ')', '}', ']' we check the top of the stack, if they both compliment each other, we pop and continue else we increment the counter and continue without popping out. After traversing the string, we output the answer as sum of counter and stack's size. In this approach the above example will not work as that extra '{' will break the approach.
Another approach is similar to above ie. we push the opening type of parentheses and if we find a closing type and if the stack's top compliment it, we pop and continue with the string, else we will pop out till we get a matching string and for every pop we increment the counter. After traversing the string, the total value is sum of counter and stack's size. But that will not work for cases like {{{{]}}}} where the character ']' will pop out everything and it will increase the answer.
I was also thinking of combining these, more like a Dynamic Programming where we will take the maximum of either seeing the top most value or seeing till we get a match in the stack or if stack becomes empty. But I am not sure on whether these 2 are the only cases to consider.
Explanation
We will process our input string character by character and update certain information about brackets encountered so far. For each bracket type, create a stack that keeps positions of uncompensated opening brackets. Basically, it says how many closing brackets of the current type are needed to make the string valid at the time of checking.
For each bracket of the input, do one of the following:
If the bracket is an opening one (any type), just add its position to the corresponding stack.
Otherwise, it's a closing bracket. If there are no opening brackets in the stack, just increment the resulting sum - unbalanced closing bracket can be compensated right away.
Finally, it's a closing bracket and there are opening brackets in the stack of the current type. So, add the number of all unbalanced brackets of the other types that are located between the last opening bracket of the same type and the current bracket! Don't forget to remove the matching elements from the stacks.
At the end, add a remaining size of each stack to the resulting sum because there may still be unbalanced opening brackets of each type.
Code
I created a simple solution in C++, but it can be easily converted to any other language if needed:
#include <iostream>
#include <stack>
#include <unordered_map>
bool isOpeningBracket(char bracket) {
return bracket == '(' || bracket == '[' || bracket == '{';
}
int main() {
std::string line;
std::cin >> line;
std::unordered_map<char, char> closingToOpeningBracket = {
{')', '('},
{']', '['},
{'}', '{'}
};
std::unordered_map<char, std::unique_ptr<std::stack<uint64_t>>> bracketsMap;
bracketsMap['{'] = std::make_unique<std::stack<uint64_t>>();
bracketsMap['['] = std::make_unique<std::stack<uint64_t>>();
bracketsMap['('] = std::make_unique<std::stack<uint64_t>>();
uint64_t addOperations = 0;
for(auto i = 0; i < line.size(); i++) {
auto bracket = line[i];
bool isOpening = isOpeningBracket(bracket);
auto key = bracket;
if (!isOpening) {
key = closingToOpeningBracket[bracket];
}
auto &bracketStack = bracketsMap[key];
if (isOpening) {
bracketStack->push(i);
} else if (!bracketStack->empty()) {
auto openingBracketPosition = bracketStack->top();
bracketStack->pop();
for (auto & [key, value] : bracketsMap) {
while (!value->empty() && value->top() > openingBracketPosition) {
addOperations++;
value->pop();
}
}
} else {
addOperations++;
}
}
for (auto & [key, value] : bracketsMap) {
addOperations += value->size();
}
std::cout << addOperations << "\n";
return 0;
}
Time and Space Complexity
The time and space complexity of this solution is O(n).
Just Think Greedily, for every closing tag there must be an opening tag if it is not so then we have to add an opening bracket.
So we can find the minimum add by iterating over the string and keeping the count of opening brackets. So when we encounter an opening bracket we increase our count variable and when we encounter a closing bracket we decrease our count variable if we have some positive count otherwise if the count is zero it means that we have to add an opening bracket here. Below is the code for this greedy approach. Time Complexity O(n) and Space Complexity O(1).
int minAddToMakeValid(string s) {
int cnt1 = 0 , cnt2 = 0, cnt3 = 0, ans = 0;
for(char ch : s){
if(ch == '(')cnt1++;
else if(ch == ')'){
if(cnt1==0)ans++;
else cnt1--;
}
if(ch == '{')cnt2++;
else if(ch == '}'){
if(cnt2==0)ans++;
else cnt2--;
}
if(ch == '[')cnt3++;
else if(ch == ']'){
if(cnt3==0)ans++;
else cnt3--;
}
}
return ans + cnt1 + cnt2 + cnt3;
}
You can do this in O(n^3) time (for any number of bracket types) with dynamic programming. This is not a lower bound on the runtime, but it appears that a greedy approach doesn't work for this problem.
First, it's helpful to realize that the 'minimum additions to balance' is the same as the 'minimum deletions to balance' for any bracket string, since the deletion framework is easier to work with. To see why this is true, consider a minimum set of additions: for every bracket that is now matched but was unmatched before, we could have also deleted that bracket, and vice versa.
The idea is to compute all possible bracket pairs: create a list of all indices [i, j], 0 <= i < j < n, where s[i] and s[j] are an open and closed bracket pair of the same type. Then, we find the maximum number of intervals [i, j] we can have, such that any two intervals are either nested or disjoint. This is exactly the requirements to be balanced, and, if you're curious, means that we're looking for the maximum size trivially perfect subgraph of the intersection graph formed by our intervals.
There are O(n^2) intervals, so any modification of this approach has an O(n^2) lower bound. We sort these intervals (by start, then by end if tied), and use dynamic programming (DP) to find the maximum number of nested or disjoint intervals we can have.
Our DP equation has 3 parameters: left, right, and min_index. [left, right] is an inclusive range of indices of s we are allowed to use, and min_index is the smallest index (in our interval list) interval we are allowed to use. If we know the leftmost interval that we can feasibly use, say, [start, end], the answer will come from either using or not using this interval. If we don't use it, we get dp(left, right, min_index+1). If we do use the interval, we add the maximum number of intervals we can nest inside (start, end), plus the maximum number of intervals starting strictly after end. This is 1 + dp(start+1, end-1, min_index+1) + dp(end+1, right, min_index+1).
For a fuller definition:
dp(left, right, min_index) :=
maximum number of intervals from interval_list[min_index:]
that are contained in [left, right] and all pairwise nested or disjoint.
Also, let
first_index := max(smallest index of an interval starting at or after left,
min_index)
so that interval_list[first_index] = (first_start, first_end).
dp(left, right, min_index) = 0 if (left > right or first_index >= length(interval_list)),
max(dp(left, right, first_index+1),
1
+ dp(first_start+1, first_end-1, first_index+1)
+ dp(first_end+1, right, first_index+1))
otherwise.
Here's a Python implementation of the algorithm:
def balance_multi_string(s: str) -> int:
"""Given a multi-paren string s, return minimum deletions to balance
it. 'Balanced' means all parentheses are matched, and
all pairs from different types are either nested or disjoint
Runs in O(n^3) time.
"""
open_brackets = {'{', '[', '('}
closed_brackets = {'}', ']', ')'}
bracket_partners = {'{': '}', '[': ']', '(': ')',
'}': '{', ']': '[', ')': '('}
n = len(s)
bracket_type_to_open_locations = collections.defaultdict(list)
intervals = []
for i, x in enumerate(s):
if x in closed_brackets:
for j in bracket_type_to_open_locations[bracket_partners[x]]:
intervals.append((j, i))
else:
bracket_type_to_open_locations[x].append(i)
if len(intervals) == 0:
return n
intervals.sort()
num_intervals = len(intervals)
#functools.lru_cache(None)
def point_to_first_interval_strictly_after(point: int) -> int:
"""Given a point, return index of first interval starting
strictly after, or num_intervals if there is none."""
if point > intervals[-1][0]:
return num_intervals
if point < intervals[0][0]:
return 0
return bisect.bisect_right(intervals, (point, n + 2))
#functools.lru_cache(None)
def dp(left: int, right: int, min_index: int) -> int:
"""Given inclusive range [left,right], and minimum interval index,
return the maximum number of intervals we can add
within this range so that all added intervals
are either nested or disjoint."""
if left >= right or min_index >= num_intervals:
return 0
starting_idx = max(point_to_first_interval_strictly_after(left - 1), min_index)
if starting_idx == num_intervals or intervals[starting_idx][0] >= right:
return 0
first_start, first_end = intervals[starting_idx]
best_answer = dp(first_start, right, starting_idx + 1) # Without first interval
if first_end <= right: # If we include the first interval
best_answer = max(best_answer,
1
+ dp(first_start + 1, first_end - 1, starting_idx + 1)
+ dp(first_end + 1, right, starting_idx + 1))
return best_answer
return n - 2 * dp(0, n - 1, 0)
Examples:
( [ ( [ ) } ] --> 3
} ( } [ ) [ { } --> 4
} ( } } ) ] ) { --> 6
{ ) { ) { [ } } --> 4
) ] } { } [ ( { --> 6
] ) } } ( [ } { --> 8
I have been working on an exercise from google's dev tech guide. It is called Compression and Decompression you can check the following link to get the description of the problem Challenge Description.
Here is my code for the solution:
public static String decompressV2 (String string, int start, int times) {
String result = "";
for (int i = 0; i < times; i++) {
inner:
{
for (int j = start; j < string.length(); j++) {
if (isNumeric(string.substring(j, j + 1))) {
String num = string.substring(j, j + 1);
int times2 = Integer.parseInt(num);
String temp = decompressV2(string, j + 2, times2);
result = result + temp;
int next_j = find_next(string, j + 2);
j = next_j;
continue;
}
if (string.substring(j, j + 1).equals("]")) { // Si es un bracket cerrado
break inner;
}
result = result + string.substring(j,j+1);
}
}
}
return result;
}
public static int find_next(String string, int start) {
int count = 0;
for (int i = start; i < string.length(); i++) {
if (string.substring(i, i+1).equals("[")) {
count= count + 1;
}
if (string.substring(i, i +1).equals("]") && count> 0) {
count = count- 1;
continue;
}
if (string.substring(i, i +1).equals("]") && count== 0) {
return i;
}
}
return -111111;
}
I will explain a little bit about the inner workings of my approach. It is a basic solution involves use of simple recursion and loops.
So, let's start from the beggining with a simple decompression:
DevTech.decompressV2("2[3[a]b]", 0, 1);
As you can see, the 0 indicates that it has to iterate over the string at index 0, and the 1 indicates that the string has to be evaluated only once: 1[ 2[3[a]b] ]
The core here is that everytime you encounter a number you call the algorithm again(recursively) and continue where the string insides its brackets ends, that's the find_next function for.
When it finds a close brackets, the inner loop breaks, that's the way I choose to make the stop sign.
I think that would be the main idea behind the algorithm, if you read the code closely you'll get the full picture.
So here are some of my concerns about the way I've written the solution:
I could not find a more clean solution to tell the algorithm were to go next if it finds a number. So I kind of hardcoded it with the find_next function. Is there a way to do this more clean inside the decompress func ?
About performance, It wastes a lot of time by doing the same thing again, when you have a number bigger than 1 at the begging of a bracket.
I am relatively to programming so maybe this code also needs an improvement not in the idea, but in the ways It's written. So would be very grateful to get some suggestions.
This is the approach I figure out but I am sure there are a couple more, I could not think of anyone but It would be great if you could tell your ideas.
In the description it tells you some things that you should be awared of when developing the solutions. They are: handling non-repeated strings, handling repetitions inside, not doing the same job twice, not copying too much. Are these covered by my approach ?
And the last point It's about tets cases, I know that confidence is very important when developing solutions, and the best way to give confidence to an algorithm is test cases. I tried a few and they all worked as expected. But what techniques do you recommend for developing test cases. Are there any softwares?
So that would be all guys, I am new to the community so I am open to suggestions about the how to improve the quality of the question. Cheers!
Your solution involves a lot of string copying that really slows it down. Instead of returning strings that you concatenate, you should pass a StringBuilder into every call and append substrings onto that.
That means you can use your return value to indicate the position to continue scanning from.
You're also parsing repeated parts of the source string more than once.
My solution looks like this:
public static String decompress(String src)
{
StringBuilder dest = new StringBuilder();
_decomp2(dest, src, 0);
return dest.toString();
}
private static int _decomp2(StringBuilder dest, String src, int pos)
{
int num=0;
while(pos < src.length()) {
char c = src.charAt(pos++);
if (c == ']') {
break;
}
if (c>='0' && c<='9') {
num = num*10 + (c-'0');
} else if (c=='[') {
int startlen = dest.length();
pos = _decomp2(dest, src, pos);
if (num<1) {
// 0 repetitions -- delete it
dest.setLength(startlen);
} else {
// copy output num-1 times
int copyEnd = startlen + (num-1) * (dest.length()-startlen);
for (int i=startlen; i<copyEnd; ++i) {
dest.append(dest.charAt(i));
}
}
num=0;
} else {
// regular char
dest.append(c);
num=0;
}
}
return pos;
}
I would try to return a tuple that also contains the next index where decompression should continue from. Then we can have a recursion that concatenates the current part with the rest of the block in the current recursion depth.
Here's JavaScript code. It takes some thought to encapsulate the order of operations that reflects the rules.
function f(s, i=0){
if (i == s.length)
return ['', i];
// We might start with a multiplier
let m = '';
while (!isNaN(s[i]))
m = m + s[i++];
// If we have a multiplier, we'll
// also have a nested expression
if (s[i] == '['){
let result = '';
const [word, nextIdx] = f(s, i + 1);
for (let j=0; j<Number(m); j++)
result = result + word;
const [rest, end] = f(s, nextIdx);
return [result + rest, end]
}
// Otherwise, we may have a word,
let word = '';
while (isNaN(s[i]) && s[i] != ']' && i < s.length)
word = word + s[i++];
// followed by either the end of an expression
// or another multiplier
const [rest, end] = s[i] == ']' ? ['', i + 1] : f(s, i);
return [word + rest, end];
}
var strs = [
'2[3[a]b]',
'10[a]',
'3[abc]4[ab]c',
'2[2[a]g2[r]]'
];
for (const s of strs){
console.log(s);
console.log(JSON.stringify(f(s)));
console.log('');
}
I am writing a program that calculates a Riemann sum based on user input. The program will split the function into 1000 rectangles (yes I know I haven't gotten that math in there yet) and sum them up and return the answer. I am using go routines to compute the 1000 rectangles but am getting an
fatal error: all go routines are asleep - deadlock!
What is the correct way to handle multiple go routines? I have been looking around and haven't seen an example that resembles my case? I'm new and want to adhere to standards. Here is my code (it is runnable if you'd like to see what a typical use case of this is - however it does break)
package main
import "fmt"
import "time"
//Data type to hold 'part' of function; ie. "4x^2"
type Pair struct {
coef, exp int
}
//Calculates the y-value of a 'part' of the function and writes this to the channel
func calc(c *chan float32, p Pair, x float32) {
val := x
//Raise our x value to the power, contained in 'p'
for i := 1; i < p.exp; i++ {
val = val * val
}
//Read existing answer from channel
ans := <-*c
//Write new value to the channel
*c <- float32(ans + (val * float32(p.coef)))
}
var c chan float32 //Channel
var m map[string]Pair //Map to hold function 'parts'
func main() {
c = make(chan float32, 1001) //Buffered at 1001
m = make(map[string]Pair)
var counter int
var temp_coef, temp_exp int
var check string
var up_bound, low_bound float32
var delta float32
counter = 1
check = "default"
//Loop through as long as we have no more function 'parts'
for check != "n" {
fmt.Print("Enter the coefficient for term ", counter, ": ")
fmt.Scanln(&temp_coef)
fmt.Print("Enter the exponent for term ", counter, ": ")
fmt.Scanln(&temp_exp)
fmt.Print("Do you have more terms to enter (y or n): ")
fmt.Scanln(&check)
fmt.Println("")
//Put data into our map
m[string(counter)] = Pair{temp_coef, temp_exp}
counter++
}
fmt.Print("Enter the lower bound: ")
fmt.Scanln(&low_bound)
fmt.Print("Enter the upper bound: ")
fmt.Scanln(&up_bound)
//Calculate the delta; ie. our x delta for the riemann sum
delta = (float32(up_bound) - float32(low_bound)) / float32(1000)
//Make our go routines here to add
for i := low_bound; i < up_bound; i = i + delta {
//'counter' is indicative of the number of function 'parts' we have
for j := 1; j < counter; j++ {
//Go routines made here
go calc(&c, m[string(j)], i)
}
}
//Wait for the go routines to finish
time.Sleep(5000 * time.Millisecond)
//Read the result?
ans := <-c
fmt.Print("Answer: ", ans)
}
It dead locks because both the calc() and the main() function reads from the channel before anyone gets to write to it.
So you will end up having every (non-main) go routine blocking at:
ans := <-*c
waiting for someone other go routine to enter a value into the channel. There fore none of them gets to the next line where they actually write to the channel. And the main() routine will block at:
ans := <-c
Everyone is waiting = deadlock
Using buffered channels
Your solution should have the calc() function only writing to the channel, while the main() could read from it in a for-range loop, suming up the values coming from the go-routines.
You will also need to add a way for main() to know when there will be no more values arriving, perhaps by using a sync.WaitGroup (maybe not the best, since main isn't suppose to wait but rather sum things up) or an ordinary counter.
Using shared memory
Sometimes it is not necessarily a channel you need. Having a shared value that you update with the sync/atomic package (atomic add doesn't work on floats) lock with a sync.Mutex works fine too.
This is a question from one of the online coding challenge (which has completed).
I just need some logic for this as to how to approach.
Problem Statement:
We have two strings A and B with the same super set of characters. We need to change these strings to obtain two equal strings. In each move we can perform one of the following operations:
1. swap two consecutive characters of a string
2. swap the first and the last characters of a string
A move can be performed on either string.
What is the minimum number of moves that we need in order to obtain two equal strings?
Input Format and Constraints:
The first and the second line of the input contains two strings A and B. It is guaranteed that the superset their characters are equal.
1 <= length(A) = length(B) <= 2000
All the input characters are between 'a' and 'z'
Output Format:
Print the minimum number of moves to the only line of the output
Sample input:
aab
baa
Sample output:
1
Explanation:
Swap the first and last character of the string aab to convert it to baa. The two strings are now equal.
EDIT : Here is my first try, but I'm getting wrong output. Can someone guide me what is wrong in my approach.
int minStringMoves(char* a, char* b) {
int length, pos, i, j, moves=0;
char *ptr;
length = strlen(a);
for(i=0;i<length;i++) {
// Find the first occurrence of b[i] in a
ptr = strchr(a,b[i]);
pos = ptr - a;
// If its the last element, swap with the first
if(i==0 && pos == length-1) {
swap(&a[0], &a[length-1]);
moves++;
}
// Else swap from current index till pos
else {
for(j=pos;j>i;j--) {
swap(&a[j],&a[j-1]);
moves++;
}
}
// If equal, break
if(strcmp(a,b) == 0)
break;
}
return moves;
}
Take a look at this example:
aaaaaaaaab
abaaaaaaaa
Your solution: 8
aaaaaaaaab -> aaaaaaaaba -> aaaaaaabaa -> aaaaaabaaa -> aaaaabaaaa ->
aaaabaaaaa -> aaabaaaaaa -> aabaaaaaaa -> abaaaaaaaa
Proper solution: 2
aaaaaaaaab -> baaaaaaaaa -> abaaaaaaaa
You should check if swapping in the other direction would give you better result.
But sometimes you will also ruin the previous part of the string. eg:
caaaaaaaab
cbaaaaaaaa
caaaaaaaab -> baaaaaaaac -> abaaaaaaac
You need another swap here to put back the 'c' to the first place.
The proper algorithm is probably even more complex, but you can see now what's wrong in your solution.
The A* algorithm might work for this problem.
The initial node will be the original string.
The goal node will be the target string.
Each child of a node will be all possible transformations of that string.
The current cost g(x) is simply the number of transformations thus far.
The heuristic h(x) is half the number of characters in the wrong position.
Since h(x) is admissible (because a single transformation can't put more than 2 characters in their correct positions), the path to the target string will give the least number of transformations possible.
However, an elementary implementation will likely be too slow. Calculating all possible transformations of a string would be rather expensive.
Note that there's a lot of similarity between a node's siblings (its parent's children) and its children. So you may be able to just calculate all transformations of the original string and, from there, simply copy and recalculate data involving changed characters.
You can use dynamic programming. Go over all swap possibilities while storing all the intermediate results along with the minimal number of steps that took you to get there. Actually, you are going to calculate the minimum number of steps for every possible target string that can be obtained by applying given rules for a number times. Once you calculate it all, you can print the minimum number of steps, which is needed to take you to the target string. Here's the sample code in JavaScript, and its usage for "aab" and "baa" examples:
function swap(str, i, j) {
var s = str.split("");
s[i] = str[j];
s[j] = str[i];
return s.join("");
}
function calcMinimumSteps(current, stepsCount)
{
if (typeof(memory[current]) !== "undefined") {
if (memory[current] > stepsCount) {
memory[current] = stepsCount;
} else if (memory[current] < stepsCount) {
stepsCount = memory[current];
}
} else {
memory[current] = stepsCount;
calcMinimumSteps(swap(current, 0, current.length-1), stepsCount+1);
for (var i = 0; i < current.length - 1; ++i) {
calcMinimumSteps(swap(current, i, i + 1), stepsCount+1);
}
}
}
var memory = {};
calcMinimumSteps("aab", 0);
alert("Minimum steps count: " + memory["baa"]);
Here is the ruby logic for this problem, copy this code in to rb file and execute.
str1 = "education" #Sample first string
str2 = "cnatdeiou" #Sample second string
moves_count = 0
no_swap = 0
count = str1.length - 1
def ends_swap(str1,str2)
str2 = swap_strings(str2,str2.length-1,0)
return str2
end
def swap_strings(str2,cp,np)
current_string = str2[cp]
new_string = str2[np]
str2[cp] = new_string
str2[np] = current_string
return str2
end
def consecutive_swap(str,current_position, target_position)
counter=0
diff = current_position > target_position ? -1 : 1
while current_position!=target_position
new_position = current_position + diff
str = swap_strings(str,current_position,new_position)
# p "-------"
# p "CP: #{current_position} NP: #{new_position} TP: #{target_position} String: #{str}"
current_position+=diff
counter+=1
end
return counter,str
end
while(str1 != str2 && count!=0)
counter = 1
if str1[-1]==str2[0]
# p "cross match"
str2 = ends_swap(str1,str2)
else
# p "No match for #{str2}-- Count: #{count}, TC: #{str1[count]}, CP: #{str2.index(str1[count])}"
str = str2[0..count]
cp = str.rindex(str1[count])
tp = count
counter, str2 = consecutive_swap(str2,cp,tp)
count-=1
end
moves_count+=counter
# p "Step: #{moves_count}"
# p str2
end
p "Total moves: #{moves_count}"
Please feel free to suggest any improvements in this code.
Try this code. Hope this will help you.
public class TwoStringIdentical {
static int lcs(String str1, String str2, int m, int n) {
int L[][] = new int[m + 1][n + 1];
int i, j;
for (i = 0; i <= m; i++) {
for (j = 0; j <= n; j++) {
if (i == 0 || j == 0)
L[i][j] = 0;
else if (str1.charAt(i - 1) == str2.charAt(j - 1))
L[i][j] = L[i - 1][j - 1] + 1;
else
L[i][j] = Math.max(L[i - 1][j], L[i][j - 1]);
}
}
return L[m][n];
}
static void printMinTransformation(String str1, String str2) {
int m = str1.length();
int n = str2.length();
int len = lcs(str1, str2, m, n);
System.out.println((m - len)+(n - len));
}
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
String str1 = scan.nextLine();
String str2 = scan.nextLine();
printMinTransformation("asdfg", "sdfg");
}
}
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 7 years ago.
Improve this question
Definition:
A palindrome is a word, phrase, number or other sequence of units that has the property of reading the same in either direction
How to check if the given string is a palindrome?
This was one of the FAIQ [Frequently Asked Interview Question] a while ago but that mostly using C.
Looking for solutions in any and all languages possible.
PHP sample:
$string = "A man, a plan, a canal, Panama";
function is_palindrome($string)
{
$a = strtolower(preg_replace("/[^A-Za-z0-9]/","",$string));
return $a==strrev($a);
}
Removes any non-alphanumeric characters (spaces, commas, exclamation points, etc.) to allow for full sentences as above, as well as simple words.
Windows XP (might also work on 2000) or later BATCH script:
#echo off
call :is_palindrome %1
if %ERRORLEVEL% == 0 (
echo %1 is a palindrome
) else (
echo %1 is NOT a palindrome
)
exit /B 0
:is_palindrome
set word=%~1
set reverse=
call :reverse_chars "%word%"
set return=1
if "$%word%" == "$%reverse%" (
set return=0
)
exit /B %return%
:reverse_chars
set chars=%~1
set reverse=%chars:~0,1%%reverse%
set chars=%chars:~1%
if "$%chars%" == "$" (
exit /B 0
) else (
call :reverse_chars "%chars%"
)
exit /B 0
Language agnostic meta-code then...
rev = StringReverse(originalString)
return ( rev == originalString );
C# in-place algorithm. Any preprocessing, like case insensitivity or stripping of whitespace and punctuation should be done before passing to this function.
boolean IsPalindrome(string s) {
for (int i = 0; i < s.Length / 2; i++)
{
if (s[i] != s[s.Length - 1 - i]) return false;
}
return true;
}
Edit: removed unnecessary "+1" in loop condition and spent the saved comparison on removing the redundant Length comparison. Thanks to the commenters!
C#: LINQ
var str = "a b a";
var test = Enumerable.SequenceEqual(str.ToCharArray(),
str.ToCharArray().Reverse());
A more Ruby-style rewrite of Hal's Ruby version:
class String
def palindrome?
(test = gsub(/[^A-Za-z]/, '').downcase) == test.reverse
end
end
Now you can call palindrome? on any string.
Unoptimized Python:
>>> def is_palindrome(s):
... return s == s[::-1]
Java solution:
public class QuickTest {
public static void main(String[] args) {
check("AmanaplanacanalPanama".toLowerCase());
check("Hello World".toLowerCase());
}
public static void check(String aString) {
System.out.print(aString + ": ");
char[] chars = aString.toCharArray();
for (int i = 0, j = (chars.length - 1); i < (chars.length / 2); i++, j--) {
if (chars[i] != chars[j]) {
System.out.println("Not a palindrome!");
return;
}
}
System.out.println("Found a palindrome!");
}
}
Using a good data structure usually helps impress the professor:
Push half the chars onto a stack (Length / 2).
Pop and compare each char until the first unmatch.
If the stack has zero elements: palindrome.
*in the case of a string with an odd Length, throw out the middle char.
C in the house. (not sure if you didn't want a C example here)
bool IsPalindrome(char *s)
{
int i,d;
int length = strlen(s);
char cf, cb;
for(i=0, d=length-1 ; i < length && d >= 0 ; i++ , d--)
{
while(cf= toupper(s[i]), (cf < 'A' || cf >'Z') && i < length-1)i++;
while(cb= toupper(s[d]), (cb < 'A' || cb >'Z') && d > 0 )d--;
if(cf != cb && cf >= 'A' && cf <= 'Z' && cb >= 'A' && cb <='Z')
return false;
}
return true;
}
That will return true for "racecar", "Racecar", "race car", "racecar ", and "RaCe cAr". It would be easy to modify to include symbols or spaces as well, but I figure it's more useful to only count letters(and ignore case). This works for all palindromes I've found in the answers here, and I've been unable to trick it into false negatives/positives.
Also, if you don't like bool in a "C" program, it could obviously return int, with return 1 and return 0 for true and false respectively.
Here's a python way. Note: this isn't really that "pythonic" but it demonstrates the algorithm.
def IsPalindromeString(n):
myLen = len(n)
i = 0
while i <= myLen/2:
if n[i] != n[myLen-1-i]:
return False
i += 1
return True
Delphi
function IsPalindrome(const s: string): boolean;
var
i, j: integer;
begin
Result := false;
j := Length(s);
for i := 1 to Length(s) div 2 do begin
if s[i] <> s[j] then
Exit;
Dec(j);
end;
Result := true;
end;
I'm seeing a lot of incorrect answers here. Any correct solution needs to ignore whitespace and punctuation (and any non-alphabetic characters actually) and needs to be case insensitive.
A few good example test cases are:
"A man, a plan, a canal, Panama."
"A Toyota's a Toyota."
"A"
""
As well as some non-palindromes.
Example solution in C# (note: empty and null strings are considered palindromes in this design, if this is not desired it's easy to change):
public static bool IsPalindrome(string palindromeCandidate)
{
if (string.IsNullOrEmpty(palindromeCandidate))
{
return true;
}
Regex nonAlphaChars = new Regex("[^a-z0-9]");
string alphaOnlyCandidate = nonAlphaChars.Replace(palindromeCandidate.ToLower(), "");
if (string.IsNullOrEmpty(alphaOnlyCandidate))
{
return true;
}
int leftIndex = 0;
int rightIndex = alphaOnlyCandidate.Length - 1;
while (rightIndex > leftIndex)
{
if (alphaOnlyCandidate[leftIndex] != alphaOnlyCandidate[rightIndex])
{
return false;
}
leftIndex++;
rightIndex--;
}
return true;
}
EDIT: from the comments:
bool palindrome(std::string const& s)
{
return std::equal(s.begin(), s.end(), s.rbegin());
}
The c++ way.
My naive implementation using the elegant iterators. In reality, you would probably check
and stop once your forward iterator has past the halfway mark to your string.
#include <string>
#include <iostream>
using namespace std;
bool palindrome(string foo)
{
string::iterator front;
string::reverse_iterator back;
bool is_palindrome = true;
for(front = foo.begin(), back = foo.rbegin();
is_palindrome && front!= foo.end() && back != foo.rend();
++front, ++back
)
{
if(*front != *back)
is_palindrome = false;
}
return is_palindrome;
}
int main()
{
string a = "hi there", b = "laval";
cout << "String a: \"" << a << "\" is " << ((palindrome(a))? "" : "not ") << "a palindrome." <<endl;
cout << "String b: \"" << b << "\" is " << ((palindrome(b))? "" : "not ") << "a palindrome." <<endl;
}
boolean isPalindrome(String str1) {
//first strip out punctuation and spaces
String stripped = str1.replaceAll("[^a-zA-Z0-9]", "");
return stripped.equalsIgnoreCase((new StringBuilder(stripped)).reverse().toString());
}
Java version
Here's my solution, without using a strrev. Written in C#, but it will work in any language that has a string length function.
private static bool Pal(string s) {
for (int i = 0; i < s.Length; i++) {
if (s[i] != s[s.Length - 1 - i]) {
return false;
}
}
return true;
}
Here's my solution in c#
static bool isPalindrome(string s)
{
string allowedChars = "abcdefghijklmnopqrstuvwxyz"+
"1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ";
string compareString = String.Empty;
string rev = string.Empty;
for (int i = 0; i <= s.Length - 1; i++)
{
char c = s[i];
if (allowedChars.IndexOf(c) > -1)
{
compareString += c;
}
}
for (int i = compareString.Length - 1; i >= 0; i--)
{
char c = compareString[i];
rev += c;
}
return rev.Equals(compareString,
StringComparison.CurrentCultureIgnoreCase);
}
Here's a Python version that deals with different cases, punctuation and whitespace.
import string
def is_palindrome(palindrome):
letters = palindrome.translate(string.maketrans("",""),
string.whitespace + string.punctuation).lower()
return letters == letters[::-1]
Edit: Shamelessly stole from Blair Conrad's neater answer to remove the slightly clumsy list processing from my previous version.
C++
std::string a = "god";
std::string b = "lol";
std::cout << (std::string(a.rbegin(), a.rend()) == a) << " "
<< (std::string(b.rbegin(), b.rend()) == b);
Bash
function ispalin { [ "$( echo -n $1 | tac -rs . )" = "$1" ]; }
echo "$(ispalin god && echo yes || echo no), $(ispalin lol && echo yes || echo no)"
Gnu Awk
/* obvious solution */
function ispalin(cand, i) {
for(i=0; i<length(cand)/2; i++)
if(substr(cand, length(cand)-i, 1) != substr(cand, i+1, 1))
return 0;
return 1;
}
/* not so obvious solution. cough cough */
{
orig = $0;
while($0) {
stuff = stuff gensub(/^.*(.)$/, "\\1", 1);
$0 = gensub(/^(.*).$/, "\\1", 1);
}
print (stuff == orig);
}
Haskell
Some brain dead way doing it in Haskell
ispalin :: [Char] -> Bool
ispalin a = a == (let xi (y:my) = (xi my) ++ [y]; xi [] = [] in \x -> xi x) a
Plain English
"Just reverse the string and if it is the same as before, it's a palindrome"
Ruby:
class String
def is_palindrome?
letters_only = gsub(/\W/,'').downcase
letters_only == letters_only.reverse
end
end
puts 'abc'.is_palindrome? # => false
puts 'aba'.is_palindrome? # => true
puts "Madam, I'm Adam.".is_palindrome? # => true
An obfuscated C version:
int IsPalindrome (char *s)
{
char*a,*b,c=0;
for(a=b=s;a<=b;c=(c?c==1?c=(*a&~32)-65>25u?*++a,1:2:c==2?(*--b&~32)-65<26u?3:2:c==3?(*b-65&~32)-(*a-65&~32)?*(b=s=0,a),4:*++a,1:0:*++b?0:1));
return s!=0;
}
This Java code should work inside a boolean method:
Note: You only need to check the first half of the characters with the back half, otherwise you are overlapping and doubling the amount of checks that need to be made.
private static boolean doPal(String test) {
for(int i = 0; i < test.length() / 2; i++) {
if(test.charAt(i) != test.charAt(test.length() - 1 - i)) {
return false;
}
}
return true;
}
Another C++ one. Optimized for speed and size.
bool is_palindrome(const std::string& candidate) {
for(std::string::const_iterator left = candidate.begin(), right = candidate.end(); left < --right ; ++left)
if (*left != *right)
return false;
return true;
}
Lisp:
(defun palindrome(x) (string= x (reverse x)))
Three versions in Smalltalk, from dumbest to correct.
In Smalltalk, = is the comparison operator:
isPalindrome: aString
"Dumbest."
^ aString reverse = aString
The message #translateToLowercase returns the string as lowercase:
isPalindrome: aString
"Case insensitive"
|lowercase|
lowercase := aString translateToLowercase.
^ lowercase reverse = lowercase
And in Smalltalk, strings are part of the Collection framework, you can use the message #select:thenCollect:, so here's the last version:
isPalindrome: aString
"Case insensitive and keeping only alphabetic chars
(blanks & punctuation insensitive)."
|lowercaseLetters|
lowercaseLetters := aString
select: [:char | char isAlphabetic]
thenCollect: [:char | char asLowercase].
^ lowercaseLetters reverse = lowercaseLetters
Note that in the above C++ solutions, there was some problems.
One solution was inefficient because it passed an std::string by copy, and because it iterated over all the chars, instead of comparing only half the chars. Then, even when discovering the string was not a palindrome, it continued the loop, waiting its end before reporting "false".
The other was better, with a very small function, whose problem was that it was not able to test anything else than std::string. In C++, it is easy to extend an algorithm to a whole bunch of similar objects. By templating its std::string into "T", it would have worked on both std::string, std::wstring, std::vector and std::deque. But without major modification because of the use of the operator <, the std::list was out of its scope.
My own solutions try to show that a C++ solution won't stop at working on the exact current type, but will strive to work an anything that behaves the same way, no matter the type. For example, I could apply my palindrome tests on std::string, on vector of int or on list of "Anything" as long as Anything was comparable through its operator = (build in types, as well as classes).
Note that the template can even be extended with an optional type that can be used to compare the data. For example, if you want to compare in a case insensitive way, or even compare similar characters (like è, é, ë, ê and e).
Like king Leonidas would have said: "Templates ? This is C++ !!!"
So, in C++, there are at least 3 major ways to do it, each one leading to the other:
Solution A: In a c-like way
The problem is that until C++0X, we can't consider the std::string array of chars as contiguous, so we must "cheat" and retrieve the c_str() property. As we are using it in a read-only fashion, it should be ok...
bool isPalindromeA(const std::string & p_strText)
{
if(p_strText.length() < 2) return true ;
const char * pStart = p_strText.c_str() ;
const char * pEnd = pStart + p_strText.length() - 1 ;
for(; pStart < pEnd; ++pStart, --pEnd)
{
if(*pStart != *pEnd)
{
return false ;
}
}
return true ;
}
Solution B: A more "C++" version
Now, we'll try to apply the same solution, but to any C++ container with random access to its items through operator []. For example, any std::basic_string, std::vector, std::deque, etc. Operator [] is constant access for those containers, so we won't lose undue speed.
template <typename T>
bool isPalindromeB(const T & p_aText)
{
if(p_aText.empty()) return true ;
typename T::size_type iStart = 0 ;
typename T::size_type iEnd = p_aText.size() - 1 ;
for(; iStart < iEnd; ++iStart, --iEnd)
{
if(p_aText[iStart] != p_aText[iEnd])
{
return false ;
}
}
return true ;
}
Solution C: Template powah !
It will work with almost any unordered STL-like container with bidirectional iterators
For example, any std::basic_string, std::vector, std::deque, std::list, etc.
So, this function can be applied on all STL-like containers with the following conditions:
1 - T is a container with bidirectional iterator
2 - T's iterator points to a comparable type (through operator =)
template <typename T>
bool isPalindromeC(const T & p_aText)
{
if(p_aText.empty()) return true ;
typename T::const_iterator pStart = p_aText.begin() ;
typename T::const_iterator pEnd = p_aText.end() ;
--pEnd ;
while(true)
{
if(*pStart != *pEnd)
{
return false ;
}
if((pStart == pEnd) || (++pStart == pEnd))
{
return true ;
}
--pEnd ;
}
}
A simple Java solution:
public boolean isPalindrome(String testString) {
StringBuffer sb = new StringBuffer(testString);
String reverseString = sb.reverse().toString();
if(testString.equalsIgnoreCase(reverseString)) {
return true;
else {
return false;
}
}
Many ways to do it. I guess the key is to do it in the most efficient way possible (without looping the string). I would do it as a char array which can be reversed easily (using C#).
string mystring = "abracadabra";
char[] str = mystring.ToCharArray();
Array.Reverse(str);
string revstring = new string(str);
if (mystring.equals(revstring))
{
Console.WriteLine("String is a Palindrome");
}
In Ruby, converting to lowercase and stripping everything not alphabetic:
def isPalindrome( string )
( test = string.downcase.gsub( /[^a-z]/, '' ) ) == test.reverse
end
But that feels like cheating, right? No pointers or anything! So here's a C version too, but without the lowercase and character stripping goodness:
#include <stdio.h>
int isPalindrome( char * string )
{
char * i = string;
char * p = string;
while ( *++i ); while ( i > p && *p++ == *--i );
return i <= p && *i++ == *--p;
}
int main( int argc, char **argv )
{
if ( argc != 2 )
{
fprintf( stderr, "Usage: %s <word>\n", argv[0] );
return -1;
}
fprintf( stdout, "%s\n", isPalindrome( argv[1] ) ? "yes" : "no" );
return 0;
}
Well, that was fun - do I get the job ;^)
Using Java, using Apache Commons String Utils:
public boolean isPalindrome(String phrase) {
phrase = phrase.toLowerCase().replaceAll("[^a-z]", "");
return StringUtils.reverse(phrase).equals(phrase);
}