Issue with getting 2 chars from string using indexer - c#-3.0

I am facing an issue in reading char values.
See my program below. I want to evaluate an infix expression.
As you can see I want to read '10' , '*', '20' and then use them...but if I use string indexer s[0] will be '1' and not '10' and hence I am not able to get the expected result.
Can you guys suggest me something? Code is in c#
class Program
{
static void Main(string[] args)
{
string infix = "10*2+20-20+3";
float result = EvaluateInfix(infix);
Console.WriteLine(result);
Console.ReadKey();
}
public static float EvaluateInfix(string s)
{
Stack<float> operand = new Stack<float>();
Stack<char> operator1 = new Stack<char>();
int len = s.Length;
for (int i = 0; i < len; i++)
{
if (isOperator(s[i])) // I am having an issue here as s[i] gives each character and I want the number 10
operator1.Push(s[i]);
else
{
operand.Push(s[i]);
if (operand.Count == 2)
Compute(operand, operator1);
}
}
return operand.Pop();
}
public static void Compute(Stack<float> operand, Stack<char> operator1)
{
float operand1 = operand.Pop();
float operand2 = operand.Pop();
char op = operator1.Pop();
if (op == '+')
operand.Push(operand1 + operand2);
else
if(op=='-')
operand.Push(operand1 - operand2);
else
if(op=='*')
operand.Push(operand1 * operand2);
else
if(op=='/')
operand.Push(operand1 / operand2);
}
public static bool isOperator(char c)
{
bool result = false;
if (c == '+' || c == '-' || c == '*' || c == '/')
result = true;
return result;
}
}
}

You'll need to split the string - which means working out exactly how you want to split the string. I suspect you'll find Regex.Split to be the most appropriate splitting tool in this case, as you're dealing with patterns. Alternatively, you may want to write your own splitting routine.
Do you only need to deal with integers and operators? How about whitespace? Brackets? Leading negative numbers? Multiplication by negative numbers (e.g. "3*-5")?

Store the numerical value in a variable, and push that when you encounter an operator or the end of the string:
int num = 0;
foreach (char c in s) {
if (isOperator(c)) {
if (num != 0) {
operand.Push(num);
num = 0;
}
operator1.Push(c);
if (operand.Count == 2) {
Compute(operand, operator1);
}
} else {
num = num * 10 + (int)(c - '0');
}
}
if (num != 0) {
operand.Push(num);
}

Related

make a function which calculate the number of same nearby character in flutter like aabcddaabb => 2abc2d2a2b

can anybody help me to build the function mentioned above I am using dart in the flutter and want this function
make a function which calculate the number of same nearby character in flutter like aabcddaabb => 2abc2d2a2b
Same
void main() {
var input = 'aabcddaabb';
print(getret(input));
}
String getret(String input) {
var ret = '';
var cc = '';
var co = 0;
cut(){
var c = input[0];
input = input.substring(1);
return c;
}
write(){
if(co == 1) ret = '$ret$cc';
if(co > 1) ret = '$ret$co$cc';
}
while(input.isNotEmpty){
final c = cut();
if(c != cc){
write();
cc = c;
co = 1;
}else{
co ++;
}
}
write();
return ret; // 2abc2d2a2b
}
There's probably a smarter and shorter way to do it, but here's a possible solution:
String string = 'aaabcddaabb';
String result = '';
String lastMatch = '';
int count = 0;
while (string.isNotEmpty) {
if (string[0] != lastMatch) {
result += '${count > 1 ? count : ''}$lastMatch';
lastMatch = string[0];
count = 0;
}
count++;
string = string.substring(1);
}
result += '${count > 1 ? count : ''}$lastMatch';
print(result); //3abc2d2a2b
I also came up with this smarter solution. Even though it's nice that it's a single expression it's maybe not very readable:
String string = 'aaabcddaabb';
String result = string.split('').fold<String>(
'',
(r, e) => r.isNotEmpty && e == r[r.length - 1]
? r.length > 1 &&
int.tryParse(r.substring(r.length - 2, r.length - 1)) != null
? '${r.substring(0, r.length - 2)}${int.parse(r.substring(r.length - 2, r.length - 1)) + 1}$e'
: '${r.substring(0, r.length - 1)}2$e'
: '$r$e');
print(result); //3abc2d2a2b

How to convert double into string with 2 significant digits?

So i have small double values and i need to convert them into string in order to display in my app. But i care only about first two significant digits.
It should work like this:
convert(0.000000000003214324) = '0.0000000000032';
convert(0.000003415303) = '0.0000034';
We can convert double to string, then check every index and take up to two nonzero (also .) strings. But the issue comes on scientific notation for long double.
You can check Convert long double to string without scientific notation (Dart)
We need to find exact String value in this case. I'm taking help from this answer.
String convert(String number) {
String result = '';
int maxNonZeroDigit = 2;
for (int i = 0; maxNonZeroDigit > 0 && i < number.length; i++) {
result += (number[i]);
if (number[i] != '0' && number[i] != '.') {
maxNonZeroDigit -= 1;
}
}
return result;
}
String toExact(double value) {
var sign = "";
if (value < 0) {
value = -value;
sign = "-";
}
var string = value.toString();
var e = string.lastIndexOf('e');
if (e < 0) return "$sign$string";
assert(string.indexOf('.') == 1);
var offset =
int.parse(string.substring(e + (string.startsWith('-', e + 1) ? 1 : 2)));
var digits = string.substring(0, 1) + string.substring(2, e);
if (offset < 0) {
return "${sign}0.${"0" * ~offset}$digits";
}
if (offset > 0) {
if (offset >= digits.length) return sign + digits.padRight(offset + 1, "0");
return "$sign${digits.substring(0, offset + 1)}"
".${digits.substring(offset + 1)}";
}
return digits;
}
void main() {
final num1 = 0.000000000003214324;
final num2 = 0.000003415303;
final v1 = convert(toExact(num1));
final v2 = convert(toExact(num2));
print("num 1 $v1 num2 $v2");
}
Run on dartPad

How to replace n occurrence of a substring in a string in dart?

I want to replace n occurrence of a substring in a string.
myString = "I have a mobile. I have a cat.";
How I can replace the second have of myString
hope this simple function helps. You can also extract the function contents if you don't wish a function. It's just two lines with some
Dart magic
void main() {
String myString = 'I have a mobile. I have a cat.';
String searchFor='have';
int replaceOn = 2;
String replaceText = 'newhave';
String result = customReplace(myString,searchFor,replaceOn,replaceText);
print(result);
}
String customReplace(String text,String searchText, int replaceOn, String replaceText){
Match result = searchText.allMatches(text).elementAt(replaceOn - 1);
return text.replaceRange(result.start,result.end,replaceText);
}
Something like that should work:
String replaceNthOccurrence(String input, int n, String from, String to) {
var index = -1;
while (--n >= 0) {
index = input.indexOf(from, ++index);
if (index == -1) {
break;
}
}
if (index != -1) {
var result = input.replaceFirst(from, to, index);
return result;
}
return input;
}
void main() {
var myString = "I have a mobile. I have a cat.";
var replacedString = replaceNthOccurrence(myString, 2, "have", "had");
print(replacedString); // prints "I have a mobile. I had a cat."
}
This would be a better solution to undertake as it check the fallbacks also. Let me list down all the scenarios:
If position is 0 then it will replace all occurrence.
If position is correct then it will replace at same location.
If position is wrong then it will send back input string.
If substring does not exist in input then it will send back input string.
void main() {
String input = "I have a mobile. I have a cat.";
print(replacenth(input, 'have', 'need', 1));
}
/// Computes the nth string replace.
String replacenth(String input, String substr, String replstr,int position) {
if(input.contains(substr))
{
var splittedStr = input.split(substr);
if(splittedStr.length == 0)
return input;
String finalStr = "";
for(int i = 0; i < splittedStr.length; i++)
{
finalStr += splittedStr[i];
if(i == (position - 1))
finalStr += replstr;
else if(i < (splittedStr.length - 1))
finalStr += substr;
}
return finalStr;
}
return input;
}
let's try with this
void main() {
var myString = "I have a mobile. I have a cat.I have a cat";
print(replaceInNthOccurrence(myString, "have", "test", 1));
}
String replaceInNthOccurrence(
String stringToChange, String searchingWord, String replacingWord, int n) {
if(n==1){
return stringToChange.replaceFirst(searchingWord, replacingWord);
}
final String separator = "#######";
String splittingString =
stringToChange.replaceAll(searchingWord, separator + searchingWord);
var splitArray = splittingString.split(separator);
print(splitArray);
String result = "";
for (int i = 0; i < splitArray.length; i++) {
if (i % n == 0) {
splitArray[i] = splitArray[i].replaceAll(searchingWord, replacingWord);
}
result += splitArray[i];
}
return result;
}
here the regex
void main() {
var myString = "I have a mobile. I have a cat. I have a cat. I have a cat.";
final newString =
myString.replaceAllMapped(new RegExp(r'^(.*?(have.*?){3})have'), (match) {
return '${match.group(1)}';
});
print(newString.replaceAll(" "," had "));
}
Demo link
Here it is one more variant which allows to replace any occurrence in subject string.
void main() {
const subject = 'I have a dog. I have a cat. I have a bird.';
final result = replaceStringByOccurrence(subject, 'have', '*have no*', 0);
print(result);
}
/// Looks for `occurrence` of `search` in `subject` and replace it with `replace`.
///
/// The occurrence index is started from 0.
String replaceStringByOccurrence(
String subject, String search, String replace, int occurence) {
if (occurence.isNegative) {
throw ArgumentError.value(occurence, 'occurrence', 'Cannot be negative');
}
final regex = RegExp(r'have');
final matches = regex.allMatches(subject);
if (occurence >= matches.length) {
throw IndexError(occurence, matches, 'occurrence',
'Cannot be more than count of matches');
}
int index = -1;
return subject.replaceAllMapped(regex, (match) {
index += 1;
return index == occurence ? replace : match.group(0)!;
});
}
Tested on dartpad.

How to determine if a string can be manipulated to be rewritten as a palindrome?

I believe this can be achieved by counting the instances for each character in that string. Even if a single character in that string is repeated at least twice, we can declare that string as a palindrome.
For example: bbcccc can be rewritten as bccccb or ccbbcc.
edified can be rewritten as deified.
Some book mentioned we should be using hash table. I think we can just use a list and check for the character count.
Do you think the logic is correct?
Yes, the main idea is to count the times of each char existing in the string. And it will be true if the string has at most one char occurs odd times and all others even times.
For example:
aabbcc => acbbca
aabcc => acbca
aabbb => abbba
No. You don't have to use a hash map (as some of the other answers suggest). But the efficiency of the solution will be determined by the algorithm you use.
Here is a solution that only tracks odd characters. If we get 2 odds, we know it can't be a scrambled palindrome. I use an array to track the odd count. I reuse the array index 0 over and over until I find an odd. Then I use array index 1. If I find 2 odds, return false!
Solution without a hash map in javascript:
function isScrambledPalindrome(input) {
// TODO: Add error handling code.
var a = input.split("").sort();
var char, nextChar = "";
var charCount = [ 0 ];
var charIdx = 0;
for ( var i = 0; i < a.length; ++i) {
char = a[i];
nextChar = a[i + 1] || "";
charCount[charIdx]++;
if (char !== nextChar) {
if (charCount[charIdx] % 2 === 1) {
if (charCount.length > 1) {
// A scrambled palindrome can only have 1 odd char count.
return false;
}
charIdx = 1;
charCount.push(0);
} else if (charCount[charIdx] % 2 === 0) {
charCount[charIdx] = 0;
}
}
}
return true;
}
console.log("abc: " + isScrambledPalindrome("abc")); // false
console.log("aabbcd: " + isScrambledPalindrome("aabbcd")); // false
console.log("aabbb: " + isScrambledPalindrome("aabbb")); // true
console.log("a: " + isScrambledPalindrome("a")); // true
Using a hash map, I found a cool way to only track the odd character counts and still determine the answer.
Fun javascript hash map solution:
function isScrambledPalindrome( input ) {
var chars = {};
input.split("").forEach(function(char) {
if (chars[char]) {
delete chars[char]
} else {
chars[char] = "odd" }
});
return (Object.keys(chars).length <= 1);
}
isScrambledPalindrome("aba"); // true
isScrambledPalindrome("abba"); // true
isScrambledPalindrome("abca"); // false
Any string can be palindrome only if at most one character occur odd no. of times and all other characters must occur even number of times.
The following program can be used to check whether a palindrome can be string or not.
vector<int> vec(256,0); //Vector for all ASCII characters present.
for(int i=0;i<s.length();++i)
{
vec[s[i]-'a']++;
}
int odd_count=0,flag=0;
for(int i=0;i<vec.size();++i)
{
if(vec[i]%2!=0)
odd_count++;
if(odd_count>1)
{
flag=1;
cout<<"Can't be palindrome"<<endl;
break;
}
}
if(flag==0)
cout<<"Yes can be palindrome"<<endl;
My code check if can it is palindrome or can be manipulated to Palindrome
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
//Tested on windows 64 bit arhc by using cygwin64 and GCC
bool isPalindrome (char *text);
int main()
{
char text[100]; // it could be N with defining N
bool isPal,isPosPal = false;
printf("Give me a string to test if it is Anagram of Palindrome\n");
gets(text);
isPal = isPalindrome(text);
isPosPal = isAnagramOfPalindrome(text);
if(isPal == false)
{
printf("Not a palindrome.\n");
}
else
{
printf("Palindrome.\n");
}
if(isPosPal == false)
{
printf("Not Anagram of Palindrome\n");
}
else
{
printf("Anagram of Palindrome\n");
}
return 0;
}
bool isPalindrome (char *text) {
int begin, middle, end, length = 0;
length = getLength(text);
end = length - 1;
middle = length/2;
for (begin = 0; begin < middle; begin++)
{
if (text[begin] != text[end])
{
return false;
}
end--;
}
if (begin == middle)
return true;
}
int getLength (char *text) {
int length = 0;
while (text[length] != '\0')
length++;
printf("length: %d\n",length);
return length;
}
int isAnagramOfPalindrome (char *text) {
int length = getLength(text);
int i = 0,j=0;
bool arr[26] = {false};
int counter = 0;
//char string[100]="neveroddoreven";
int a;
for (i = 0; i < length; i++)
{
a = text[i];
a = a-97;
if(arr[a])
{
arr[a] = false;
}
else
{
arr[a] = true;
}
}
for(j = 0; j < 27 ; j++)
{
if (arr[a] == true)
{
counter++;
}
}
printf("counter: %d\n",counter);
if(counter > 1)
{
return false;
}
else if(counter == 1)
{
if(length % 2 == 0)
return false;
else
return true;
}
else if(counter == 0)
{
return true;
}
}
as others have posted, the idea is to have each character occur an even number of times for an even length string, and one character an odd number of times for an odd length string.
The reason the books suggest using a hash table is due to execution time. It is an O(1) operation to insert into / retrieve from a hash map. Yes a list can be used but the execution time will be slightly slower as the sorting of the list will be O(N log N) time.
Pseudo code for a list implementation would be:
sortedList = unsortedList.sort;
bool oddCharFound = false;
//if language does not permit nullable char then initialise
//current char to first element, initialise count to 1 and loop from i=1
currentChar = null;
currentCharCount = 0;
for (int i=0; i <= sortedList.Length; i++) //start from first element go one past end of list
{
if(i == sortedList.Length
|| sortedList[i] != currentChar)
{
if(currentCharCount % 2 = 1)
{
//check if breaks rule
if((sortedList.Length % 2 = 1 && oddCharFound)
|| oddCharFound)
{
return false;
}
else
{
oddCharFound = true;
}
}
if(i!= sortedList.Length)
{
currentCharCount = 1;
currentChar = sortedList[i];
}
}
else
{
currentCharCount++;
}
}
return true;
Here is a simple solution using an array; no sort needed
#include <stdio.h>
#include <stdlib.h>
int main()
{
int a[256] = { 0 };
unsigned char i[] = {"aaBcBccc"};
unsigned char *p = &i[0];
int c = 0;
int j;
int flag = 0;
while (*p != 0)
{
a[*p]++;
p++;
}
for(j=0; j<256; j++)
{
if(a[j] & 1)
{
c++;
if(c > 1)
{
flag = 1;
break;
}
}
}
if(flag)
printf("Nope\n");
else
printf("yup\n");
return 0;
}
C#:
bool ok = s.GroupBy(c => c).Select(g => g.Count()).Where(c => c == 1).Count() < 2;
This solution, however, does use hashing.
Assuming all input characters are lower case letters.
#include<stdio.h>
int main(){
char *str;
char arr[27];
int j;
int a;
j = 0;
printf("Enter the string : ");
scanf("%s", str);
while (*str != '\0'){
a = *str;
a = a%27;
if(arr[a] == *str){
arr[a]=0;
j--;
}else{
arr[a] = *str;
j++;
}
*str++;
}
if(j==0 || j== -1 || j==1){
printf ("\nThe string can be a palindrome\n");
}
}

STM32 atoi and strtol sometimes missing first 2 digits

I am reading a value sent over RS485 which is the value of an encoder I first check if it has returned an E character (the encoder is reporting an error) and if not then do the following
*position = atoi( buffer );
// Also tried *position = (s32) strtol(buffer,NULL,10);
The value in the buffer is 4033536 and position gets set to 33536 this does not happen every time in this function probably 1 in 1000 times maybe although I am not counting. Setting the program counter back and doing the line again if has failed returns the same result but starting the debugger again causes the value to convert correctly.
I am using keil uvision 4, its a custom board using an stm32f103vet6 and the stm32f10 library V2.0.1 This one has really got me stumped never come across something like this before any help would be much appreciated.
Thanks
As no one knows I will just post what I ended up doing which was to write my own function for convertion not ideal but it worked.
bool cdec2s32(char* text, s32 *destination)
{
s32 tempResult = 0;
char currentChar;
u8 numDigits = 0;
bool negative = FALSE;
bool warning = FALSE;
if(*text == '-')
{
negative = TRUE;
text++;
}
while(*text != 0x00 && *text != '\r') //while current character not null or carridge return
{
numDigits++;
if(*text >= '0' && *text <= '9')
{
currentChar = *text;
currentChar -= '0';
if((warning && ((currentChar > 7 && !negative) || currentChar > 8 && negative )) || numDigits > 10) // Check number not too large
{
tempResult = 2147483647;
if(negative)
tempResult *= -1;
*destination = tempResult;
return FALSE;
}
tempResult *= 10;
tempResult += currentChar;
text++;
if(numDigits >= 9)
{
if(tempResult >= 214748364)
{
warning = TRUE; //Need to check next digit as close to limit
}
}
}
else if(*text == '.' || *text == ',')
{
break;
}
else
return FALSE;
}
if(negative)
tempResult *= -1;
*destination = tempResult;
return TRUE;
}