The following method checks for all triplets with the given value/sum. I want to write a #Test method for this method that returns an integer and also takes in an arraylist and a variable as parameters. Is there a way I can write a junit5 test for the following code-
int triplets(ArrayList<Integer> a, int sum)
{
int l, r;
int count = 0;
for (int i = 0; i < a.size() - 2; i++) {
l = i + 1;
r = a.size() - 1;
while (l < r) {
if ( a.get(i) + a.get(l) + a.get(r) == sum) {
count++;
System.out.print("Triplet " + count +" is " + a.get(i) + ", " + a.get(l) + ", " + a.get(r) + "\n");
l++;
r--;
}
else if (a.get(i) + a.get(l) + a.get(r) < sum)
l++;
else // arr.get(i) + arr.get(l) + arr.get(r) > sum
r--;
}
}
if(count!=0)
{
System.out.print("Total triplets present: " + count);
return 1;
}
else
return -1;
}
In JUnit5, you could use a ParameterizedTest with a MethodSource for this.
static Stream<Arguments> arrayListProvider() {
List<Arguments> argList = new ArrayList<>();
List<Integer> testList;
int sum, expectedResult;
// Repeat this as required to cover the set of test cases of interest
// Test set 1
testList = new ArrayList<>(Arrays.asList(
1, 2, 3, 4, 5, 6, 7, 8, 9));
sum = 9;
expectedResult = 1;
argList.add(arguments(testList, sum, expectedResult));
// Test set 2
testList = new ArrayList<>(Arrays.asList(
1, 2, 3, 4, 5));
sum = 13;
expectedResult = -1;
argList.add(arguments(testList, sum, expectedResult));
//...
return argList.stream();
}
#ParameterizedTest
#MethodSource("arrayListProvider")
void testTriplets(ArrayList<Integer> a, int sum, int expectedResult) {
assertEquals(expectedResult, triplets(a, sum));
}
Problem description:
I'm trying to solve a problem on the internet and I wasn't able to pass all testcases, well, because my logic is flawed and incorrect. The flaw: I assumed starting to the closest 'F' point will get me to the shortest paths always, at all cases.
Thinks I thought of:
Turning this into a graph problem and solve it based on it. > don't think this would work because of the constraint?
Try to obtain all possible solution combinations > does not scale, if !8 combination exist.
#include <iostream>
#include <utility>
#include <string>
#include <vector>
#include <queue>
using namespace std;
#define N 4
#define M 4
int SearchingChallenge(string strArr[], int arrLength) {
int n = arrLength, m = n, steps = 0, food = 0;
// initial position of charlie
int init_j = 0;
int init_i = 0;
queue<pair<int,int>> q;
// directions
vector<int> offsets = {0,-1,0,1,0};
vector<pair<int,int>> food_nodes;
//store visited nodes, no need for extra work to be done.
int visited_nodes[4][4] = {{0}};
// get number of food pieces
for(int i = 0; i < m; i++){
for(int j = 0; j < n ; j++){
if(strArr[i][j] == 'F')
{
food++;
}
if(strArr[i][j] == 'C')
{
strArr[i][j] = 'O';
food_nodes.push_back({i,j});
}
}
}
while(food_nodes.size()>0){
food_nodes.erase(food_nodes.begin());
int break_flag=0;
q.push(food_nodes[0]);
while(!q.empty()){
int size = q.size();
while(size-->0){
pair<int,int> p = q.front();
q.pop();
for(int k = 0; k < 4; k++){
int ii = p.first + offsets[k], jj = p.second + offsets[k+1];
/* if(ii == 0 && jj == 3)
printf("HI"); */
if(jj >= 0 && jj < 4 && ii < 4 && ii >=0){
if(strArr[ii][jj] == 'F'){
strArr[ii][jj] = 'O';
while(!q.empty())
q.pop();
break_flag=1;
food--;
food_nodes.push_back({ii,jj});
break;
}
if(strArr[ii][jj] == 'O')
q.push({ii,jj});
if(strArr[ii][jj] == 'H' && food == 0)
return ++steps;
}
}
if(break_flag==1)
break;
}
steps++;
if(break_flag==1)
break;
}
}
return 0;
}
int main(void) {
// keep this function call here
/* Note: In C++ you first have to initialize an array and set
it equal to the stdin to test your code with arrays. */
//passing testcase
//string A[4] = {"OOOO", "OOFF", "OCHO", "OFOO"};
//failing testcase
string A[4] = {"FOOF", "OCOO", "OOOH", "FOOO"}
int arrLength = sizeof(A) / sizeof(*A);
cout << SearchingChallenge(A, arrLength);
return 0;
}
Your help is appreciated.
I have wrote the javascript solution for the mentioned problem..
function SearchingChallenge(strArr) {
// create coordinate array
const matrix = [
[0, 0], [0, 1], [0, 2], [0, 3],
[1, 0], [1, 1], [1, 2], [1, 3],
[2, 0], [2, 1], [2, 2], [2, 3],
[3, 0], [3, 1], [3, 2], [3, 3]
]
// flatten the strArr
const flattenArray = flatten(strArr)
// segreagate and map flattenArray with matrix to get coordinate of food,charlie and home
const segregatedCoordinates = flattenArray.reduce((obj, char, index) => {
if (char === 'F') obj['food'].push(matrix[index])
else if (char === 'C') obj['dog'] = matrix[index]
else if (char === 'H') obj['home'] = matrix[index]
return obj
}, { "food": [], dog: null, home: null })
// construct possible routes by permutating food coordinates
let possibleRoutes = permuate(segregatedCoordinates['food'])
// push dog and home in possibleRoutes at start and end positions
possibleRoutes = possibleRoutes.map((route) => {
return [segregatedCoordinates['dog'], ...route, segregatedCoordinates['home']]
})
// Calculate distances from every possible route
const distances = possibleRoutes.reduce((distances, route) => {
let moveLength = 0
for (let i = 0; i < route.length - 1; i++) {
let current = route[i], next = route[i + 1]
let xCoordinatePath = current[0] > next[0] ? (current[0] - next[0]) : (next[0] - current[0])
let yCoordinatePath = current[1] > next[1] ? (current[1] - next[1]) : (next[1] - current[1])
moveLength += xCoordinatePath + yCoordinatePath
}
distances.push(moveLength)
return distances
}, [])
return Math.min(...distances);
}
function permuate(arr) {
if (arr.length <= 2) return (arr.length === 2 ? [arr, [arr[1], arr[0]]] : arr)
return arr.reduce((res, ele, index) => {
res = [...res, ...permuate([...arr.slice(0, index), ...arr.slice(index + 1)]).map(val => [ele, ...val])]
return res
}, [])
}
function flatten(inputtedArr) {
return inputtedArr.reduce((arr, row) => {
arr = [...arr, ...row]
return arr
}, [])
}
console.log(SearchingChallenge(['FOOF', 'OCOO', 'OOOH', 'FOOO']));
You can write a DP solution where you have a 4x4x8 grid. The first two axis represent the x and y coordinate. The third one represent the binary encoding of which food item you picked already.
Each cell in the grid stores the best number of moves to get at this cell having eaten the specified foods. So for example, grid[2][2][2] is the cost of getting to cell (2,2) after having eaten the second piece of food only.
Then you set the value of the start cell, at third index 0 to 0, all the other cells to -1. You keep a list of the cells to propagate (sorted by least cost), and you add the start cell to it.
Then you repeatedly take the next cell to propagate, remove it and push the neighboring cell with cost +1 and updated food consume. Once you reach the destination cell with all food consumed, you're done.
That should take no more than 4x4x8 updates, with about the same order of priority queue insertion. O(n log(n)) where n is xy2^f. As long as you have few food items this will be almost instant.
C++ solution
I used both dfs and bfs for this problem
TIME COMPLEXITY - (4^(N×M))+NO_OF_FOODS×N×M
#include <bits/stdc++.h>
using namespace std;
//It is a dfs function it will find and store all the possible steps to eat all food in toHome map
void distAfterEatingAllFood(vector<vector<char>> &m, int countOfFood, int i, int j, int steps, map<pair<int,int>,int>&toHome){
if(i<0 || j<0 || i>=4 || j>=4 || m[i][j]=='*') return;
if(m[i][j]=='F') countOfFood--;
if(countOfFood==0){
if(!toHome.count({i,j}))
toHome[{i,j}] = steps;
else if(toHome[{i,j}]>steps)
toHome[{i,j}] = steps;
return;
}
char temp = m[i][j];
m[i][j] = '*';
distAfterEatingAllFood(m, countOfFood, i+1, j, steps+1, toHome);
distAfterEatingAllFood(m, countOfFood, i-1, j, steps+1, toHome);
distAfterEatingAllFood(m, countOfFood, i, j+1, steps+1, toHome);
distAfterEatingAllFood(m, countOfFood, i, j-1, steps+1, toHome);
m[i][j] = temp;
return;
}
//It is a bfs function it will iterate over the toHome map and find the shortest distance between the last food position to home
int lastFoodToHome(vector<vector<char>> &m, int i, int j, int steps){
queue<pair<pair<int, int>,int>>q;
vector<vector<int>> vis(4, vector<int>(4, 0));
q.push({{i, j}, steps});
vis[i][j] = 1;
int dirX[] = {0, 1, 0, -1};
int dirY[] = {1, 0, -1, 0};
while (!q.empty())
{
int x = q.front().first.first;
int y = q.front().first.second;
int steps = q.front().second;
q.pop();
if (m[x][y] == 'H')
return steps;
for (int k = 0; k < 4; k++)
{
int ni = x + dirX[k];
int nj = y + dirY[k];
if (ni >= 0 && nj >= 0 && ni < 4 && nj < 4 && !vis[ni][nj])
{
if(m[ni][nj] == 'H') return steps + 1;
q.push({{ni, nj}, steps + 1});
vis[i][j] = 1;
}
}
}
return INT_MAX;
}
int main()
{
vector<vector<char>> m(4, vector<char>(4));
int countOfFood = 0, x, y;
for (int i = 0; i < 4; i++){
for (int j = 0; j < 4; j++){
cin >> m[i][j];
if (m[i][j] == 'C'){
x = i;
y = j;
}
if (m[i][j] == 'F')
countOfFood++;
}
}
map<pair<int,int>,int>toHome;
distAfterEatingAllFood(m, countOfFood, x, y, 0, toHome);
int ans = INT_MAX;
for(auto &i:toHome){
ans = min(ans, lastFoodToHome(m, i.first.first, i.first.second, i.second));
}
cout<<ans;
return 0;
}
I have a c++ struct which has a dynamically allocated array as a pointer. I have a function to reverse the array, but it doesn't seem to work (I think its because the temporary variable points to the original value).
struct s {
int *array;
int length;
...
s(int n) {
this->array = new int[n];
this->length = n;
}
...
void reverse() {
for (int i = 0; i < this->length; i++) {
int n = this->array[i];
this->array[i] = this->array[this->length - i - 1];
this->array[this->length - i - 1] = n;
}
}
...
}
I think what this is doing is this->array[this->length - i - 1] = this->array[i]
Hence the array remains the same and doesn't get reversed. I don't know how to deference the array pointer or how to just take the value of this->array[i] in n.
The reason your reverse doesn't work is that you're going through the length of the whole array. You need to only go through half of it. If you go through the second half, then you're un-reversing it.
As an example, if you try to reverse [1, 2, 3, 4] you get
after i = 0: [4, 2, 3, 1]
after i = 1: [4, 3, 2, 1]
--- reversed ---
after i = 2: [4, 2, 3, 1]
after i = 3: [1, 2, 3, 4]
--- back to original ---
Instead, just make your loop
for (int i = 0; i < this->length / 2; i++) {
...
}
On a side note, using 2 indexers will simplify your code considerably:
void reverse()
{
int limit = length / 2;
for ( int front = 0 , back = length - 1; front < limit; front++ , back-- )
{
int n = array[front];
array[front] = array[back];
array[back] = n;
}
}
I have an array:
int arr[] = {1, 2, 3, 4}
How can I randomize arr[] to multi-list with No Duplicates?
FROM
arr[] = { 1, 2, 3, 4 }
TO
arr1[] = {1, 2, 3, 4}
arr2[] = {2, 1, 4, 3}
arr3[] = {3, 4, 1, 2}
arr4[] = {4, 3, 2, 1}
In this case, it is preferable to use a List<Integer> instead of int[]
List<Integer> arr = new ArrayList<Integer>();
Random random = new Random();
int randonint = arr.remove(random.nextint(arr.getSize()));
Every time this code is runned, it will grab a random int from the list arr, then you can add it to a different List/Array
So, if you want to take all values from one list, and randomly place them to 3 other lists, use the following code:
List<Integer> arr1 = new ArrayList<Integer>();
List<Integer> to1 = new ArrayList<Integer>();
List<Integer> to2 = new ArrayList<Integer>();
List<Integer> to3 = new ArrayList<Integer>();
Random random = new Random();
for (int i = 1 ; i <= 10 ; i++) {
arr1.add(i);
}
for (int count = 0 ; count < arr1.size() ; count++) {
List<Integer> arr = new ArrayList<Integer>();
int randomvalue = arr.remove(random.nextint(arr.getSize()));
switch (random.nextInt(3)) {
case 0:
to1.add(randomvalue);
case 1:
to2.add(randomvalue);
case 2:
to2.add(randomvalue);
}
}
public static void GenerateRandomArray()
{
var inputArray = new[] {1, 2, 3, 4};
var outputArray = GetRandomArray(inputArray);
PrintArray(outputArray);
}
private static void PrintArray(int[,] outputArray)
{
for (var i = 0; i < outputArray.GetLength(0); i += 1)
{
for (var j = 0; j < outputArray.GetLength(1); j += 1)
{
Console.Write(outputArray[i, j]);
}
Console.WriteLine();
}
}
private static int[,] GetRandomArray(int[] inputArray)
{
var lengthOfArray = inputArray.Length;
var outputArray = new int[lengthOfArray,lengthOfArray];
for (var i = 0; i < lengthOfArray; i++)
{
var counterShifter = i;
for (var j = 0; j < lengthOfArray;j++)
{
outputArray[i, j] = inputArray[counterShifter];
counterShifter = counterShifter + 1 < lengthOfArray
? counterShifter + 1 :
0;
}
}
return outputArray;
}
Suppose I have two lists:
x = [[1,2,3],[5,4,20],[9,100,7]]
y = [[1,1,1],[1,1,1],[1,1,1]]
I am trying to get z = x - y so that my array should be like
z = [[0, 1, 2], [4, 3, 19], [8, 99, 6]]
For example in Java
public class Main {
public static void main(String[] args) {
int[][] x = new int[][]{
{1,2,3},
{5,4,20},
{9,100,7}
};
int[][] y = new int[][]{
{1,1,1},
{1,1,1},
{1,1,1}
};
int[][] result = new int[3][3];
for(int i = 0; i < 3; i++){
for(int j = 0; j < 3; j++){
result[i][j] = x[i][j] - y[i][j];
System.out.print(result[i][j]+ " ");
}
System.out.print(" | ");
}
}
}