Removing the last element in an array - arrays

This is a question about finding distinct values in an array of ten numbers. The user provides 10 numbers. I've written the code, separated the code into two files(another condition to the assignment) but I found myself at a loss when the answer returns with a trailing 0.
I need to know how to remove the trailing 0 from the array. If it was a string I could do this easily. Unfortunately, I need to return the answer as an array between the two files.
I have researched the topic and found that "splice" works but I can't figure out how it works in my code. The only solution that I came up with is to remove all 0s from the code (my first example below). Unfortunately, the user should be able to include 0s if he or she decides to input a zero.
//document 1
public static void main(String[] args){
Scanner s = new Scanner(System.in);
String strOfArray = " ";
String Values = "";
int arr[]=new int[1000000];
System.out.print("Entered 10 integers:\t\t\t ");
for(int i = 0; i<10; i++)
arr[i] = s.nextInt();
for (int j=0; j<10; j++)
strOfArray += (arr[j]+ " ");
System.out.println ("Array before processing:"+ "\t" + strOfArray);
System.out.print("Array after processing:\t\t ");
DistinctValues.getValues(arr);
}
}
//document 2
public class DistinctValues {
public static void getValues(int[] arr){
String Values = "";
for (int i=0; i<arr.length; i++){
boolean isUnique = false;
for(int j=0; j<i; j++){
if (arr[i] == arr[j]){
isUnique = true;
break;}}
if(!isUnique){
System.out.print(arr[i] +" ");}}}}
I added all my code for better clarification. Thank you.

So here's the solution after trial and error and me realizing that I had a set number of elements so I didn't need to be ambiguous about what I set "i" to. Since I have 10 variables, I could just make it i one less than 10 and the program couldn't spit out an extra 0.
if(!isUnique && i<10){
System.out.print(arr[i] +" ");}
But since I'm learning this. Can someone help me with an array that wasn't set to 10 integers or set to however many the user wanted. Make it i < variable?

Related

How do I get 4 digits number but without any digit number repeated?

As title said, I want to randomly generate a 4-digit number (it's okay to have zero in the first digit), but the number itself couldn't contain the same number.
For example, 1234 is okay, 2234 is not okay, because 2 has repeated.
Moreover, if it got repeated, then create another number again until the 4-digit number has no longer the same number within.
I couldn't figure it out. I stuck on some point, especially in while-loop.
Here's my code with C#.
Please help me with this.
public class GuessNumber
{
public int[] answer;
public void newGame()
{
int[] answer = new int[4];
var random = new Random(Guid.NewGuid().GetHashCode());
for (int i = 0; i < answer.Length; i++)
{
answer[i] = random.Next(0, 10);
}
this.answer = RandomCheck(answer);
}
public int[] RandomCheck(int[] answer)
{
bool repetition = true;
for (int i = 0; i < answer.Length; i++)
{
do
{
repetition = false;
for (int k = 0; k < i; k++)
{
if (answer[i] != answer[k]) continue;
else
{
newGame();
continue;
}
} while (repetition);
return answer;
}
Please help with this, make it could automatically generate the right number.

How do I replace all occurrences in an array with another array in C

I want to replace all occurrences in an array (string) with another array.
I have a code that:
stores the string in an array in which the replacing is to take place output[],
another array that stores the string to be searched for as replace[] and a third array called toBeReplacedBy and the replacing of the first occurrence works just fine but it skips the other occurrences in the output
for example:
replace[]:
abc
toBeReplacedBy[]:
xyz
output[]:
abcdefabc
becomes
xyzdefabc
but it should become:
xyzdefxyz
I suspect the problem lies with the replacer code :
//the replacer
for (i = 0; i<80; i++) {
if (output[i] == replace[i])
output[i] = toBeReplacedBy[i];
}
//debug purpose
puts("output[]:\n");
puts(output);
return 0;
}
What have I done wrong here and how could I get it to replace all occurrences in the array.
please be aware that I only wish to use stdio.h to do this
thabks in advance
Never iterate further than the array length. This leads to undefined and possibly dangerous behaviour. If you only expect strings, use something like:
int i = 0;
while(output[i] != '\0')
{
// your logic here
i++;
}
Additionally you want to check for concurrent appearances of the same characters. But in your code you only check the first three characters. Everything after that is undefinded behaviour, because you cannot know what replace[3] returns.
Something similar to this could work:
int i = 0;
int j = 0;
int k;
while(output[i] != '\0')
{
if (output[i] == replace[j])
j++;
else
j = 0;
// replace 3 with the array length of the replace[] array
if (j == 3)
{
for(k = i; j >= 0; k-- )
{
output[k] = toBeReplacedBy[j]
j--
}
j = 0;
}
i++;
}
But please check the array boundaries.
edit: Additionally as Nellie states using a debugger would help you to understand what went wrong. Go through your program step by step and look how and when values change.
First advice is to try to debug your program if it does not work.
for (i = 0; i<80; i++) {
if (output[i] == replace[i])
output[i] = toBeReplacedBy[i];
}
There are two problems in this loop.
The first is that are iterating until i is 80. Let's look what happens when i becomes 3. output[3] in case of abcdefabc is d, but what is replace[3]? Your replacement array had only 3 letters, so you have to go back in the replacement array once you finish with one occurrence of it in the original string.
The second is that you check letter by letter.
Say you original array, which you named output somehow was abkdefabc, first three letters do not match your replacement string, but you will check the first two letters they will match with the replacement's first two letters and you will incorrectly change them.
So you need to first check that the whole replacement string is there and only then replace.
You should use strlen() to know length of your array or iterate until you reach the end of a your array ('\0').
'\0' and strlen are only available for array of char.
Your loop should looks like this :
int i = 0;
int len = strlen(my_string);
while (i < len)
{
//logic here
i = i + 1;
}
OR
int i = 0;
while (my_string[i] != '\0')
{
// logic here
i = i + 1;
}

Recursive traversal of 2d array to find unique paths

I need to traverse a 2D-Array of 0's (which represent open pathways) and 1's which represent walls. I have to calculate the number of unique paths from (0,0) to (N-1,N-1) of an NxN Grid. I have written a recursive method to do this however i cannot figure out why the traversal part of my method (i.e the straight, left and right movements) are not working as expected:
public static void TraversePath(int [][] Grid, boolean[][] isTraversed, int column, int row) {
if(row < 0 || column < 0 || row > Grid[0].length || column > Grid[0].length )
return; // if you go out of bounds
if(isTraversed[column][row] == true)
return; // if you have already been to the point
if(Grid[column][row]==1) {
isTraversed[column][row] = true; // if the current point is a wall mark it as traversed
return;
}
if(Grid[column][row]!=1 && (row == Grid[0].length-1 && column == Grid[0].length-1)) { //if you get to an endpoint that isn't a wall
uniquePaths++; //counter that tallys the unique paths
isTraversed[column][row] = true;
return;
}
TraversePath(Grid,column,row+1);//Straight
TraversePath(Grid,column-1, row);//Left
TraversePath(Grid,column+1, row);//Right
}
public static void main(String[] args) {
int [][]Grid = new int[][]
{
{0,1,1,0},
{0,0,1,0},
{0,0,0,0},
{0,1,1,0}
};
boolean[][] isTraversed = new boolean[Grid.length][Grid.length];
for(int i = 0; i < Grid.length; i++) {
for(int j = 0; j< Grid.length; j++)
isTraversed[i][j] = false;
}
TraversePath(Grid,isTraversed,0,0);
System.out.println(uniquePaths);
}
I keep getting a StackOverFlow error (hey, sounds familiar) when I run this code. I figure it probably has something to do with how I am marking the edges as visited in the isTraversed boolean graph but I am not sure. Any help would be super appreciated.
This is the main method that I'm using to test the array, it's a simple 4x4 grid with 2 unique paths to (3,3).
Your Stack Overflow Error is caused by the fact that you can continuously move left then right again. Assuming that you could only move in the positive directions, you could make a very simple recursive function using dynamic programing to prevent you from getting a Stack Overflow error.
public static int possiblePaths(int[][] grid, int x,int y,int [][] dp){
if(x<0||x>=grid.length||y<0||y>=grid[0].length)
return 0;
if(dp[x][y]==-1){
dp[x][y]=possiblePaths(grid,x+1,y,dp)+possiblePaths(grid,x,y+1,dp);
}
return dp[x][y];
}
public static void main(String[] args) {
int [][]Grid = new int[][]
{
{0,1,1,0},
{0,0,1,0},
{0,0,0,0},
{0,1,1,0}
};
int [][] dp = new int[Grid.length][Grid[0].length];
for(int i = 0; i < Grid.length; i++) {
for(int j = 0; j< Grid[0].length; j++)
if(Grid[i][j]==1)
dp[i][j]=0;
else
dp[i][j]=-1;
}
dp[Grid.length-1][Grid[0].length-1]=0;
System.out.println(possiblePaths(Grid,0,0,dp));
}
What this basically states that the amount of ways to get from (x,y) to the end is the sum of # of paths from (x+1,y) and # of paths from (x,y+1) and remembers these numbers in the dp (Dynamic Programing) array so you do not need to recalculate them. In the dp array, the cells where there are walls are set to 0 because there are 0 ways to get to the end from the wall.
There are a couple of errors in this code, but the main problem is that you do not set isTraversed[column][row] = true if you just make a normal step without running into any of the if-statements.
Another big problem is, that the isTraversed array is shared across different search paths. This means that a grid-field visited in one branch of the iteration cannot be visited in another branch. Ultimately, your result will thus be always at most 1. In order to avoid this you could make a deep copy of isTraversed just before you enter the next iteration step.
boolean[][] isTraversedCopy = new boolean[isTraversed.length][isTraversed[0].length];
for(int i=0; i<isTraversed.length; i++)
for(int j=0; j<isTraversed[i].length; j++)
isTraversedCopy[i][j]=isTraversed[i][j];
TraversePath(Grid,isTraversedCopy, column,row+1);//Straight
TraversePath(Grid,isTraversedCopy, column-1, row);//Left
TraversePath(Grid,isTraversedCopy, column+1, row);//Right
Other problems are:
TraversePath(Grid,column,row+1);//Straight and the following lines are missing an argument (isTraversed)
in the first if-statement it should be
if(row < 0 || column < 0 || row >= Grid[0].length || column >= Grid[0].length)
Why is there no possibility to move to the bottom?
Optional but this will make readability of your code easier: You should change row and column to make it consistent to your representation of the gridworld and with the normal use of 2d-arrays. Additionally, your definition of straight, left, right is a bit confusing and does not fit to the grid definition.

String to Character Array

I have a problem with my code below:
public class stringToChar {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int n = in.nextInt();
char[] sCharArr;
String[] odd = new String[n];
String[] even = new String[n];
for(int i = 0; i < n; i++) {
sCharArr = in.next().toCharArray();
for(int j = 0; j < sCharArr.length; j++) {
if(j % 2 == 0)
even[i] += sCharArr[j];
else
odd[i] += sCharArr[j];
}
}
for(int i = 0; i < n; i++) {
System.out.println(even[i] + " " + odd[i]);
}
}
}
My issue is on the output it has a Null in the result. Here is a sample scenario:
2
John
Cena
Answer should be:
Jh on
Cn ea
But my code answer is:
NullJh Nullon
NullCn Nullea
Your problem is that the new arrays are initialized with all null Strings. Then your code is not assigning values to all array elements, but just to some of them!
Finally you print your array, and surprise, those values that were null and that have not been changed - are still null (and when you print a null string ... it prints "null" [ yes, null, not Null; you got a little mistake there in your output example ]
You see, you iterate from 0 to the length of your two arrays. And if the number is even, you put a value in the even[i]; and if the value is odd, it goes to odd[i]. Lets take even - in that case, odd[i] simply stays null!
One way to fix that:
List<String> even = new ArrayList<>();
List<String> odd = new ArrayList<>();
And now, instead of setting a certain index in even/odd; you simply do:
even.add(some new value);
and to add those single characters:
even.add(new String(sCharArr));
Doing so, even and odd will (in the end) contain exactly the values that you added to each list; but no "residual" nulls. For the record: the way how you split up strings, to then pull them back into a String array isn't exactly the most simple/straight forward way to solve the problem.
But I leave "further" simplifications" as exercise to the user.

C Comparing 2 strings turned into memory allocation issue

Let me start off by saying, I do realize there are a lot of questions with the exact same title, but I didn't find what I was looking for in any of them. I tried to write the following code, in order to errorcheck the user's input, so he wouldn't give 2 variables the same name. Needless to say, it failed, and that is why I am here. While printing the strings I was comparing out as strings, using printf("%s", temp[j].name); was working fine, the character-by-character printing was outputting a series of characters that, from what I know, shouldn't be there. I would like to know what this could all be about, and if there is anyway to solve it, so I can actually compare the 2, without using something from string.h
Here is the code:
#include <stdio.h>
#include <stdlib.h>
#define ARRAYLENGTH 20
typedef struct{
char name[ARRAYLENGTH];
char type[ARRAYLENGTH];
char value[ARRAYLENGTH];
}variable;
int main(){
int amount = 3;
int i, j, k;
variable * varray;
variable * temp;
int flag;
int added = 1;
varray = malloc(amount*sizeof(variable));
if (varray == NULL){
printf("error");
return 1;
}
temp = malloc(amount*sizeof(variable));
if (temp == NULL){
printf("error");
return 1;
}
printf("Give the name of variable # 1 \n");
scanf("%s", varray[0].name);
for (i = 1; i < amount; i++){
flag = 0;
while (flag == 0){
printf("Give the name of variable # %d \n", i + 1);
scanf("%s", temp[i].name);
for (j = 0; j < added; j++){
for (k = 0; temp[i].name[k] != '\0'; k++){
printf("%c,", temp[i].name[k]);
}
printf("\n");
for (k = 0; temp[i].name[k] != '\0'; k++){
if (varray[j].name[k] != temp[i].name[k]){
flag = 1;
break;
}
if (varray[j].name[k] == temp[i].name[k]){
flag = 0;
}
}
}
if (flag == 0){
printf("The variable name you gave already exists, please choose another one. \n");
}
if (flag == 1){
for (j = 0; j < ARRAYLENGTH; j++){
varray[i].name[j] = temp[i].name[j];
}
}
if(flag == 1){
added +=1;
}
}
}
for (i = 0; i < amount; i++){
printf("%s \n", varray[i].name);
}
free(varray);
free(temp);
}
The code compiles without problem, but when I tried to run it, I found that, no matter what my, as a user, input was, the flag would always be 1 in the end. The block of code
printf("\n");
for (k = 0; k < ARRAYLENGTH; k++){
printf("%c,", temp[i].name[k]);
}
printf("\n");
And when the user input is the name John, outputs the following on Visual Studio 2013's Developer command prompt:
Give the name of variable # 1
John
Give the name of variable # 2
John
J,o,h,n,
The variable name you gave already exists, please choose another one.
Give the name of variable # 2
George
G,e,o,r,g,e,
Give the name of variable # 3
George
G,e,o,r,g,e,
G,e,o,r,g,e,
The variable name you gave already exists, please choose another one.
Give the name of variable # 3
John
J,o,h,n,
J,o,h,n,
John
George
John
What I am guessing this problem is about, is that the memory the system is allocating to temp and varray are already being used elsewhere. This errorcheck is crucial for a project I have to do, so I would appreciate any help I can get in solving this problem greatly. Thanks in advance,
LukeSykpe
The problem is with your printing logic.
The scanf function writes the user input into the array, followed by a terminating `\0' character. It does not know the size of your array (20), so it doesn't touch the part of the array that it doesn't actually write.
Instead of this:
for (k = 0; k < ARRAYLENGTH; k++){
write:
for (k = 0; temp[i].name[k] != '\0'; k++) {
Note that you don't need to check for running off the end of the array here. Instead, make sure that the user string is not too big for your array. See this for how to do that.
Edit : This post is not to answer the original question, but to answer a follow-up question posted in comments. I tried to incorporate this into the previous answer, but the owner refused. So here it is.
The problem with your varray comparisons is that, with the code you are showing at least, varray is never initialized. So
if (varray[j].name[k] != temp[i].name[k])
Is a bit like taking a random byte in memory, assigning it to a variable and doing this :
if (RandomByteValue != temp[i].name[k])
Which 90% of the time will be true thus setting your flag to 1.
Essentially, you're missing a
varray[i] = lastVariableGotFromUser
At the end of each main loop.
--- Edit : Added in minor corrections to general functionality ---
Try adding in this :
int added = 1;
Then change this :
for (j = 0; j < amount; j++){
with :
for (j = 0; j < added; j++){
and add in :
if (flag == 1){
// Your for loop
added += 1;
}
What was happening was that you iterated through fields of varray that were uninitialized, and contained random memory. With those modifications (If i didn't forget one, it should work. Try to always limit your loops to only the useful iterations. If you know you only have one variable added in, don't iterate through the 3 fields.
------- Last edit to correct a detail in his code -------
So, your whole :
for (k = 0; temp[i].name[k] != '\0'; k++){
Can be deleted. Now i also know that you don't want to use string.h, However, recoding a strcmp ain't all that complicated. Let's call it
int comp_str(str, str2) // Returns 1 if they don't match, zero if they do.
then just replace your whole for with :
if (comp_str(temp[i].name, varray[j].name) == 0) {
flag = 0;
break;
}
else
flag = 1;
You only want to set the flag when a whole string has been analyzed. So pass it to another function, act upon the return value, and it works! Generally slice your code up. Easier to act/think on. (and also avoids having things like varray[j].name[k] != temp[i].name[k] which is long an not so pleasing to read, in your code.)

Resources