For this question, a dictionary was given and two strings also given, it was basically asked to reach from one string to another one just using the words in dictionary, and only one letter can be changed at a time. I came up with this solution. There were some corner cases that my code can not handle. Can you help to find all the corner cases to make this code prettier?
public static int findNumberOfSteps(String start, String end , HashSet<String> dict){
if( start == null || end == null || dict.isEmpty()){
throw new IllegalArgumentException();
}
dict.add(end);
Queue<String> wordHolder = new LinkedList<>();
Queue<Integer> distanceCount = new LinkedList<Integer>();
wordHolder.add(start);
distanceCount.add(1);
int result = Integer.MAX_VALUE;
while (!wordHolder.isEmpty()){
String currentWord = wordHolder.poll();
int currDistance = distanceCount.poll();
if(currentWord.equals(end)){
int result = currDistance;
return result;
}
for (int i = 0 ; i < currentWord.length() ; i++){
char[] charCurrentWord = currentWord.toCharArray();
for ( char c = 'a' ; c <= 'z' ; c++){
charCurrentWord[i] = c;
String newWord = new String(charCurrentWord);
if (dict.contains(newWord)){
wordHolder.add(newWord);
distanceCount.add(currDistance+1);
dict.remove(newWord);
}
}
}
}
return 0;
}
There are a couple of problems in the code. The first problem is in this code
if(currentWord.equals(end)){
result = Math.min(result, currDistance);
}
Note that when you reach the end word, that code updates the result, but then the code is going to search for ways to change the end word to something else. That's a huge waste of time, the code should continue with the while(!wordHolder.isEmpy()) loop after the end is found.
The second problem is in this code
if (dict.contains(newWord)){
wordHolder.add(newWord);
distanceCount.add(currDistance+1);
dict.remove(newWord);
}
Note that if newWord is equal to the end word, then that code removes the end word from the dictionary, which means that you'll never find the end word again.
The solution to both problems is to check for the end word inside that if statement. When the end is found, don't add it to the wordHolder and don't remove it from the dictionary.
if (dict.contains(newWord)){
if(newWord.equals(end)){
result = Math.min(result, currDistance+1);
}
else{
wordHolder.add(newWord);
distanceCount.add(currDistance+1);
dict.remove(newWord);
}
}
Related
Json string : "{\n\t"tag": "Value",\n\t"attributes": {\n\t\t"rfid": "2"\n\t},\n\t"dat": "1"\n}
I am receiving the Json string from web server part by part i.e 8bytes at a time
When i am trying to collect the data in one buffer with the below logic in C
static char *jsonString ;
bool found_json = false;
jsonString = (char*)malloc (1024, sizeof(char));
while(data[i] != "}")
{
found_json = true;
for( i = 0; i< len; i++)
{
memcpy(jsonString, data, len);
}
}
can someday throw some light that how to detect end of the string of Json as there will be two closing Json object
I think you have two proper ways: either fully parse the JSON (you can use some libraries for that) or somehow receive the length of the string (if this is a HTTP request then there should be Content-Length header which indicates the length). Things like messing with curly braces is not reliable because even a simple number like 1233 or boolean values like true are valid JSON strings.
Here is some pseudo code for finding the end of your string:
open = 0;
close = 0;
while ( visit each character in your buffer )
{
if (new character == '{')
open++;
else if (new character == '}')
close++;
if (open == 0) // Did we even start the JSON string yet?
discard character
else if (open == close) // Matching number of { and } found. We are done.
{
process JSON string
open = close = 0; // Prepare for next incoming JSON string.
}
}
I have a field to validate repeated questions. I must convert special characters into normal letters using a method, and then I use a method to skip spaces and other characters to validate if the new text is equal to the existing questions. In my local everything is working fine, but in a Production instance, it skips characters 1, f, x and b. My project in Production is mounted in Linux.
My two methods are:
replaceSpecialCharacters(output){
return output = output.replace(/á|é|í|ó|ú|ñ|ä|ë|ï|ö|ü|à|è|ì|ò|ù/ig,function (str,offset,s) {
var str = str=="á"?"a":str=="é"?"e":str=="í"?"i":str=="ó"?"o":str=="ú"?"u":str=="ñ"?"n":str;
str = str=="Á"?"A":str=="É"?"E":str=="Í"?"I":str=="Ó"?"O":str=="Ú"?"U":str=="Ñ"?"N":str;
str = str=="à"?"a":str=="è"?"e":str=="ì"?"i":str=="ò"?"o":str=="ù"?"u":str;
str = str=="À"?"A":str=="È"?"E":str=="Ì"?"I":str=="Ò"?"O":str=="Ù"?"U":str;
str = str=="ä"?"a":str=="ë"?"e":str=="ï"?"i":str=="ö"?"o":str=="ü"?"u":str;
str = str=="Ä"?"A":str=="Ë"?"E":str=="Ï"?"I":str=="Ö"?"O":str=="Ü"?"U":str;
return (str);
});
}
validateRepeatedQuestion(question): void {
var questionToCheck = this.replaceSpecialCharacters(question).replace(/[(\s)+(\¿)+(\?)+(\¡)+(\!)+(\")+(\')+]/g, "");
this.setState({isRepeated: false});
for (let i = 0; i < this.props.allQuestions.length; i++) {
var questionFromArray = this.replaceSpecialCharacters(this.props.allQuestions[i].text).replace(/[(\s)+(\¿)+(\?)+(\¡)+(\!)+(\")+(\')+]/g, "");
if(this.props.allQuestions[i].position != this.props.question.position){
if(questionFromArray.toLocaleLowerCase() == questionToCheck.toLocaleLowerCase()){
this.setState({isRepeated: true});
}
}
}
}
If I have a question like "How old are you?" and I try to add a question like "How old are you?1111" I expect the validation to take the new question as different, but the actual output says that the question is repeated, even if I'm adding numbers 1. It must be different.
The code below shows the rowtotal[0], which is the return value I'm getting from an infinite loop for every iteration. I'm trying to break the loop when all three returned values from the costcheck array are the same. This is my code:
do
{
.
.
.
/*do loop body*/
.
.
costcheck[counter3]=rowtotal[0];
if(costcheck[counter3-2]==costcheck[counter3] &&
costcheck[counter3-1]==costcheck[counter3] )
{
response=1;
}
counter3++;
printf("\t\t\t Number of iterations: %d \r", stop++);
}
while(response!=1);
Just get rid of all strange, superfluous variables. You only need to save the result of the previous iteration, together with a counter which you increase each time you find a match, rather than every time in the loop.
int counter=0;
const int COUNT_N = 3;
data_t prev=FORBIDDEN; // a value that rowdata[0] can never have
while(counter != COUNT_N)
{
...
if(prev == rowdata[0])
{
counter++;
}
else
{
counter=0;
}
prev = rowdata[0];
}
just to elaborate on Lundins Answer wich is the way to go in my opinion (would have posted as a comment, but lacking reputation...)
Only thing missing is the actual loop advancement counter (counter3 in your example):
int quitCounter=0; // Counter for quiting the loop on 3 consecutive identical values
int loopCounter=0; // Your normal rowdata index
const int QUIT_COUNT_N = 3;
#define FORBIDDEN 0xffffff // or some other value that rowdata[0] can never have
data_t prev=FORBIDDEN; // a value
do
{
...
/* do loop body, provide new value for rowtotal[0] on each iteration */
/* if you need to store the consecutive values returned in rowtotal[0] in costcheck array,
make sure that it will be big enough - if you only need to break on 3 identical values,
you can skip the entire costcheck array as Lundin proposes. */
...
costcheck[counter3]=rowtotal[0];
if(prev == costcheck[counter3])
{
quitCounter++;
}
else
{
quitCounter=0;
}
prev = costcheck[counter3];
counter3++;
} while(quitCounter!= QUIT_COUNT_N )
If you really want an infinite loop, a if(costcheck[counter-1] == costcheck[counter-2] && costcheck[counter-2] == costcheck[counter-3]) will lead to failure of program, if costcheck array has less than 3 elements. You have to be sure that it does have at least 3 elemets in this array.
BUT!!!! counter does not need to be more than 3 because as far as i get it, you want to check 3 most reciently read elements. Which means for comparison, you only need to remember 3 last values that were read.
The exapmple below stores up to 3 rowtotal[0] values, and checks if they are equal. If they are, progarm exits, if not, program gets new rowtotal[0] to the "end" of costcheck array, also the oldest value: here it's costcheck[0] is lost.
I can post the code to the example which i made, to show how the logic should work.
NOTE!!! I strongly think Lundin's and Morphine's solutions are by far better than mine.
do
{
.............
if(counter < 3)
{
costcheck[counter] = rowtotal[0];
counter++;
continue;
}
else
{
if(costcheck[counter-1] == costcheck[counter-2] && costcheck[counter-2] == costcheck[counter-3])
{
response=1;
}
else
{
costcheck[counter-3] = costcheck[counter-2];
costcheck[counter-2] = costcheck[counter-1];
costcheck[counter-1] = rowtotal[0];
}
}
}
while(response!=1);
}
Context : I'm searching for all the words contained in a 2d array (horizontally,vertically and diagonaly).
So what I do is I get all the possible words, check if they're in the given dictionary and if they are store them in an array. The thing is, I don't want it to have duplicates.
Here's a snippet of the code:
for (i=l-1;i>=0;i--){
palavra[aux]=mat[i][caux];
for (j=i;j>=0;j--){
palavra[aux]=mat[j][caux];
palavra[aux+1]='\0';
for (it=0;encontradas[it]!=NULL;it++){
if (strcmp(palavra,encontradas[it])==0)flag=1;
else flag=0;
}
if (flag==0) {
r = palavra_existe(dic,palavra);
if (r!=0) {
found[auxenc]=mystrdup(palavra);
auxenc++;
}
}
flag=0;
aux++;
}
aux=0;
}
The
if (strcmp(palavra, found[it])==0)flag=1
line is there to check if the formed worded has been found already, to avoid creating a duplicate. The problem is it doesn't work, duplicates appear anyway (as the flag variable never takes the value 1).
What could I be missing here?
The flag variable does get the value 1, but then it turns back to 0 again in the next iteration.
Set flag to zero before the loop, and when you find a match you set it to 1 and exit the loop:
flag = 0;
for (it = 0; encontradas[it] != NULL; it++) {
if (strcmp(palavra,encontradas[it]) == 0) {
flag=1;
break;
}
}
(Exiting the loop isn't needed for the logic to work, but there is no point in looping through the rest of the items once you have found a match.)
I have been working on a little test program which reads some values from a config file into variables however it seems I get odd behavior with if/else statements. For instance if I run this and print out the processed variables I get that sectorloop is 20000 even though it is defined in my cfg as 100000. I know it detects it because If I remove the else statement after the strcmp() for driveamount it works fine. This would however break the fallback if it isn't defined in the test.cfg...
int sectorloop,driveamount,q,j,p;
char cfgstring[3][128],sys_serial[128];
/*
the analyzing is broken up into 6 steps:
1: read test.cfg data into an 2d array of chars with newlines as delimiter.
2. go through each value in the array and look for the '=' this is the delimiter for the meaning=value.
3. overwrite '=' to a string terminating character '\0' C thinks the meaning specifier is the entire string while still keeping the value in memory allthough hidden
4. use string compare to match to meaning to the desired string.
5. if there is a match move the value(after the '=' in the config) to the beginning of the array. overwriting the meaning as it isn`t needed anymore
6. now we have a string which we know what meaning it belonged to and can use it in the program, sometimes it needs to be converted to int or whatever
*/
FILE *configfp=fopen("test.cfg","r");
if (configfp==NULL) {
sectorloop=50000;
driveamount=27;
sys_serial[0]='\0';
} else {
q=j=0;while ((cfgstring[j][q]=fgetc(configfp))!=EOF&&q<128&&p<3) {
if (cfgstring[j][q]==10||cfgstring[j][q]==13) {
cfgstring[j][q]='\0';
q=0;
j++;
}
else {
q++;
}
}
cfgstring[j][q]='\0';
for (q=0;q<=j;q++) {
p=0;while (cfgstring[q][p]!='='&&cfgstring[q][p]!='\0'&&p<128) {
p++;
}
cfgstring[q][p]='\0';
if ((strcmp(cfgstring[q],"host_serial"))==0) {
j=0;while (cfgstring[q][j+p+1]!='\0') {
cfgstring[q][j]=cfgstring[q][j+p+1];
j++;
}
cfgstring[q][j]='\0';
strcpy(sys_serial,cfgstring[q]);
}
if ((strcmp(cfgstring[q],"sectorloop"))==0) {
j=0;while (cfgstring[q][j+p+1]!='\0') {
cfgstring[q][j]=cfgstring[q][j+p+1];
j++;
}
cfgstring[q][j]='\0';
if ((sectorloop=atoi(cfgstring[q]))==0) {
sectorloop=50000;
}
} else {
sectorloop=20000;
}
if ((strcmp(cfgstring[q],"driveamount"))==0) {
j=0;while (cfgstring[q][j+p+1]!='\0') {
cfgstring[q][j]=cfgstring[q][j+p+1];
j++;
}
cfgstring[q][j]='\0';
if ((driveamount=atoi(cfgstring[q]))==0) {
driveamount=27;
}
} else {
driveamount=27;
}
}
}
fclose(configfp);
the cfg look like this:
host_serial=serial number
sectorloop=100000
driveamount=33
Your code logic is wrong. Basically, your code does this:
for each config string:
if string == "sectorloop"
sectorloop = value from string
else
sectorloop = default value
if string == "driveamount"
driveamount = value from string
else
driveamount = default value
Now say your input is "sectorloop=x; driveamount=y". The first pass will assign x to sectorloop and the default value to driveamount. The next pass will overwrite sectorloop with the default and assign y to driveamount.
You'll want something like this:
sectorloop = default value
driveamount = default value
for each config string:
if string == "sectorloop"
sectorloop = value from string
if string == "driveamount"
driveamount = value from string