How to generate unique chars when populating a 2D array? - java

How do I make it so that when I output the grid when I run the code, no two numbers or letters will be the same? When I currently run this code I could get 3x "L" or 2x "6", how do I make it so that they only appear once?
package polycipher;
import java.util.ArrayList;
public class Matrix {
private char[][] matrix = new char[6][6];
private int[] usedNumbers = new int[50];
{for(int x = 0; x < usedNumbers.length; x++) usedNumbers[x] = -1;}
private final char[] CIPHER_KEY = {'A','D','F','G','V','X'};
private final String validChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
public Matrix() {
int random;
for(int i = 0; i < CIPHER_KEY.length; i++) {
for(int j = 0; j < CIPHER_KEY.length; j++) {
validation: while(true) {
random = (int)(Math.random()*validChars.length()-1);
for(int k = 0; k < usedNumbers.length; k++) {
if(random == usedNumbers[k]) continue validation;
else if(usedNumbers[k]==-1) usedNumbers[k] = random;
}
break;
}
matrix[i][j] = validChars.split("")[random].charAt(0);
}
}
}
public String toString() {
String output = " A D F G V X\n";
for(int i = 0; i < CIPHER_KEY.length; i++) {
output += CIPHER_KEY[i] + " ";
for(int j = 0; j < CIPHER_KEY.length; j++) {
output += matrix[i][j] + " ";
}
output += "\n";
}
return output;
}
}

This should be much faster than validating each random choice:
Store your valid chars into an array;
char[] valid = validChars.toCharArray();
Shuffle the array;
shuffle(valid)
Go through the positions in the matrix, storing the elements in the same order they appear in the shuffled array.
assert (CIPHER_KEY.length * CIPHER_KEY.length) <= valid.length;
int k = 0;
for (int i = 0; i < CIPHER_KEY.length; i++) {
for (int j = 0; j < CIPHER_KEY.length; j++) {
matrix[i][j] = valid[k++];
}
}

Use a set and generate a new random if the old random number is in the map:
Pseudocode:
Set<Integer> set = new HashSet<Integer>();
for () {
int random = (int)(Math.random()*validChars.length()-1);
//Your code for validation here (move it to a function)
while (!set.contains(random)){
int random = (int)(Math.random()*validChars.length()-1);
//Your code for validation here (move it to a function)
}
//If we exit this loop it means the set doesn't contain the number
set.add(random);
//Insert your code here
}

Related

Randomly place 1D string array into 2D char array

I'm trying to randomly place 1D string array into 2D char array but I'm having issues with my for-loop.
userWords is 1D array of String while puzzleBoard is a 2D array of char.
I've tried
for(int i=0; i<userWords.length;i++) {
puzzleBoard[r++] = userWords[i].toCharArray();
}
but it's not placing it randomly like I want it to
So I tried
for(int i=0; i<userWords.length;i++) {
int r = rand.nextInt(ROW) + 1;
int c = rand.nextInt(COLUMN) + 1;
puzzleBoard[r][c] = userWords[i].charAt(i);
}
but it's printing only 3 char instead of the 3 strings of char into the char array.
I've also tried
puzzleBoard[r][c] = userWords[i].toCharArray();
instead of
puzzleBoard[r][c] = userWords[i].charAt(i);
But it display error "cannot convert from char[] to char"
Thank you
Full Code
public static void main(String[] args) {
String[] userWords = new String[3];
Methods.userInput(userWords); //ask user for input
Methods.fillPuzzle(puzzleBoard); //fill the puzzle with random char
for(int i=0; i<userWords.length;i++) {
int r = rand.nextInt(ROW) + 1;
int c = rand.nextInt(COLUMN) + 1;
puzzleBoard[r][c] = userWords[i].charAt(i);
}
Methods.printPuzzle(puzzleBoard); //print out the puzzle
}//end main
public static void printPuzzle(char a[][]) {
for (int i = 0; i < a.length; i++) {
for (int j = 0; j < a[i].length; j++) {
System.out.print(a[i][j] + " ");
}
System.out.print((i+1));
System.out.println();
}
}//end printPuzzle
public static void fillPuzzle(char a[][]) {
for (int i = 0; i < a.length; i++) {
for (int j = 0; j < a[i].length; j++) {
a[i][j] = '*';
}
}
}//end fillPuzzle
public static void userInput(String a[]) {
Scanner input = new Scanner(System.in);
for(int i = 0; i < a.length;i++) {
System.out.println((i+1) + ". enter word:");
a[i] = input.next().toUpperCase();
}
}//end userInput
You can try this one:
for (int i = 0; i < userWords.length; i++) {
int r = rand.nextInt(puzzleBoard.length);
int c = rand.nextInt(puzzleBoard[r].length - userWords[i].length());
for (int j = 0; j < userWords[i].length(); j++) {
puzzleBoard[r][c + j] = userWords[i].charAt(j);
}
}
And you should add something that detects whether there is already a word at this position, otherwise you would overwrite it if the random numbers point to a location where is already written a word.
I think you should use 2 for-loops because you want to select first the string and next the characters in the string.
for(int i=0; i<userWords.length;i++) {
int r = rand.nextInt(ROW) + 1;
int c = rand.nextInt(COLUMN) + 1;
for (int j = 0; j < userWords[i].length(); j++) {
puzzleBoard[r][c + j] = userWords[i].charAt(j);
}
}

Homework assignment to fill mock array with random values

How can I create xy matrix (where x <= y) with random integers (from 0 to 9) which has at least x zeros and max (xy)/2 in java?
Size of matrix (x,y) is given. Also I would like to know how to use this matrix with same integers with same index in other class (for example 'public class Game{...}'). I'm a beginner so please make it easy for me :)
My code so far:
import java.util.Random;
public class Solution {
int a[][];
public void P(int x, int y){
Random r = new Random();
a = new int[x][y];
for (int i=0; i<x; i++){
for (int j=0; j<y; j++){
a[i][j] = r.nextInt(10);
System.out.print(a[i][j] + " ");
}
System.out.println();
}
System.out.println();
int zeros = 0;
for (int i=0; i<x; i++){
for (int j=0; j<y; j++){
if(a[i][j]==0){
zeros ++;
}
}
}
System.out.println(zeros);
}
public int[][] getA() {
return a;
}
}
Random r = new Random();
a = new int[x][y];
int noZeros = r.nextInt((y*x)/2-x) + x;
boolean z[][] = new boolean[x][y];
for (int i = 0; i < noZeros; i++) {
z[r.nextInt(x)][r.nextInt(y)] = true;
}
for (int i = 0; i < x; i++) {
for (int j = 0; j < y; j++) {
if (!z[i][j]) {
a[i][j] = r.nextInt(9) + 1;
}
System.out.print(a[i][j] + " ");
}
System.out.println();
}
System.out.println();
int zeros = 0;
for (int i = 0; i < x; i++) {
for (int j = 0; j < y; j++) {
if (a[i][j] == 0) {
zeros++;
}
}
}
System.out.println(zeros);
In my solution I create first boolean matrix, which represents zeros, then I chose random number, but from 1 to 9.
I would first determine how many 0s you will have in the matrix, getting a random int from within your min/max bound. Then I would calculate the other xy - numZeros random integers. Finally, for each cell in the matrix, I would pick a random element from a combined list (your 0s + other random integers, removing the element when it is picked).

I am trying this simple sudoku

I am trying a simple sudoku program. i started by taking the values in a 3D
array and then copied them into a 1D array by using mr.serpardum's method.
i know that there is an error at the point where i am trying to find
duplicate elements,because even if i give same numbers as input the output
says "its a sudoku" but i can't to find it...apparently i can't add any
image coz i dont have enough credits
public class SecondAssignment {
#SuppressWarnings("unused")
public static void main(String[] args) throws IOException {
int i = 0, j = 0, k = 0;
boolean result = false;
int arr1[][];
arr1 = new int[3][3];
int arr2[];
arr2 = new int[9];
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
System.out.println("Enter the elements in the sudoku block");
//getting elements into array
for (i = 0; i < 3; i++) {
for (j = 0; j < 3; j++) {
arr1[i][j] = Integer.parseInt(br.readLine());
}
}
//printing it in matrix form
for (i = 0; i < 3; i++) {
for (j = 0; j < 3; j++) {
System.out.print(arr1[i][j] + "\t");
}
System.out.println(" ");
}
//copying array1 elements into array 2
for (i = 0; i < 3; i++) {
for (j = 0; j < 3; j++) {
arr2[i * 3 + j] = arr1[i][j];
}
}
//finding duplicate elements
for (i = 0; i < arr2.length; i++) {
for (int m = i + 1; m < arr2.length; m++) {
if (arr2[i] == (arr2[m])) {
System.out.println("Not a sudoku");
//result = true;
} else {
System.out.println("Its a sudoku");
//result = false;
}
}
}
}
}
You can update your code to following
//finding duplicate elements
for( i = 0; i < arr2.length; i++){
for(int m = i+1; m < arr2.length; m++){
if(arr2[i] == (arr2[m])){
result = true;
break;
}
}
}
if(result){
System.out.println("\nNot a sudoku");
}
else{
System.out.println("\nIts a sudoku");
}
You should have used break as soon as the match was found.
This code just checks if duplicate element is present in the array (of size 9) or not.

Making a nested for loop into a single for loop

I had an assignment to create an array of random number from 10-100.
Then I need to sout all the numbers not listed in the array.
I did the assignment with a nested for loops, to cross reference the arrays, then I changed all the found numbers in the array into -1. Finally I printed out the elements in the array that were not -1.
My professor told me that is it possible for me to do this assignment with only one for loop and there is no need to do a nested for loop. and make the computer run 10,000 times instead of just 100.
Is that possible? If so how?
Thank you.
package assignment.pkg1;
import java.util.Random;
public class Assignment1 {
static Random ran = new Random();
public static void main(String[] args) {
int[] arr = new int[100];
for (int i = 0; i < 100; i++) {
arr[i] = (ran.nextInt(90)) + 10;
}
InversingArray(arr);
}
public static void InversingArray(int[] randomArray) {
int[] fullArray = new int[100];
for (int i = 0; i < 100; i++) {
fullArray[i] = i;
}
for (int i = 0; i < 100; i++) {
for (int j = 1; j < 100; j++) {
if (randomArray[j] == fullArray[i]) {
fullArray[i] = -1;
}
}
}
System.out.println("These numbers are not in randomArray: ");
for (int i = 0; i < 100; i++) {
if (fullArray[i] != -1) {
System.out.println(fullArray[i]);
}
}
}
In your code you create an array to hold the possible values. If you think about it, the array index will always be equal to the number stored in the array.
fullArray[i] = i;
This is redundant.
What you are being asked to do is determine which numbers have been used: a boolean test. This means that you should have an array of boolean that is initially false (the default value of booleans in java) and is flipped to true when an equal integer is flipped to true.
Something like
int[] arr = new int[100];
for (int i = 0; i < 100; i++) {
arr[i] = (ran.nextInt(90)) + 10;
}
// ba starts with all false values
boolean ba[] == new boolean[90]; // note that the instructor said 10-100
for(int i=0; i<90; i++) {
ba[arr[i]] = true;
// lets assume arr[0] == 45
// ba[arr[0]] is the same as ba[45]
// ba[45] = true; will set that bucket of the boolean array to true
}
System.out.println("These numbers are not in randomArray: ");
for (int k = 0; k < 10; k++) {
System.out.println(k);
}
for (int j = 0; j < 90; j++) {
if (!ba[j]) { // shorthand for ba[j]==false
System.out.println(j+10); // The array starts at a base of 10
}
}
Be aware (probably the point of the exercise) that you are working with an array [0..90] that represents the numbers [10..100].
The nested loop currently looks like this:
for (int i = 0; i < 100; i++) {
for (int j = 1; j < 100; j++) {
if (randomArray[j] == fullArray[i]) {
fullArray[i] = -1;
}
}
}
But we know, that fullArray[i] is always the same as i.
So you can rewrite it to:
for (int j = 1; j < 100; j++) {
int i = randomArray[j];
fullArray[i] = -1;
}
Or even shorter:
for (int j = 1; j < 100; j++) {
fullArray[randomArray[j]] = -1;
}

Getting All Possibilities - Schoolwork

What I need to do is take a String array with each element having an exact length of 2, and find all possible combinations of the the elements, using each character within each String. By that I mean the String array {"Ss", "Ff"} returns "SF", "Sf", "sF", "sf". I have already tried a loop method that counts the iteration and then chooses a letter based on that, but it only works for arrays with a single element:
public String [] generatePossibilities(String [] s)
{
if(s[0].length() != 2)
throw new IllegalArgumentException();
String [] r = new String [s.length * 2];
for(int i = 0; i < r.length; i++)
{
r[i] = getPossibility(i, s);
}
return r;
}
private String getPossibility(int iteration, String [] source)
{
int [] choose = new int [source.length];
for(int i = 0; i < choose.length; i++)
{
choose[i] = 0;
}
for(int i = choose.length - 1; i >= 0; i--)
{
if(iteration < 1)
break;
choose[i] = 1;
iteration--;
}
String result = "";
for(int i = 0; i < source.length; i++)
result += source[i].substring(choose[i], choose[i] + 1);
return result;
}
Solved Thanks Sven!
public String [] generatePossibilities(String [] s)
{
if(s[0].length() != 2)
throw new IllegalArgumentException();
ArrayList<String> ra = new ArrayList<String>();
for(int i = s.length - 1; i >= 0; i--)
{
for(int j = 0; j < s[i].length(); j++)
{
String c = s[i].substring(j, j + 1);
if(ra.size() < 2)
{
ra.add(c);
}
else
{
for(int k = 0; k < ra.size(); k++)
{
String s1 = ra.get(k);
if(s1.substring(0, 1).equalsIgnoreCase(c))
continue;
else
{
s1 = c + s1;
ra.add(s1);
}
}
}
}
for(int j = 0; j < ra.size(); j++)
{
if(ra.get(j).length() != s.length - i)
{
ra.remove(j);
j--;
}
}
}
String [] r = new String [ra.size()];
for(int i = 0; i < r.length; i++)
{
r[i] = ra.get(i);
}
return r;
}
I would iterate the array of character tuples from last element to first. In each step you append to each current character the possibilities of the last iteration. You therefore double the elements in each step.
So for your example in the first iteration you have {Ff} and this would result to the two strings "F" and "f". In the next step you take each character of {Ss} and append each string of the last step to it getting "SF", "Sf", "sF" and "sf". You could then continue with further character tuples.

Categories

Resources