find all possible sums of a list without target - java

im trying to find all possible sums from a list.
The list consist of ints that are user inputed, and the number of inputs are decided by the user aswell( see code).
What i want is to check all possible sums without having a target.
The reason i dont want a target is because the program is then later suposed to chose one of these sums which is closest to 1000.
So if i was to pick 1000 as target i wouldnt be able to get say 1001.
Example input from user:
5 // user chose 5 numbers.
500,400,300,50,60 // numbers chosen by user.
Output would then be:
1010 // because 500+400+60+50= 1010 and closest to 1000.
Next example could be:
3 // user chose 3 numbers.
1,2,3 // numbers chosen by user.
Output would then be:
6 // because 1+2+3 = 6.
So back to my original question, how do is this done? Everytime i search "all possible sums of a list of ints" or simular i get with a target and it dosent work in this example.
public static void main(String[] args) throws Exception {
int bästaVikt;
int räknare = 0;
Scanner sc = new Scanner(System.in);
ArrayList<Integer> mylist = new ArrayList<Integer>();
int s;
s = sc.nextInt();
int ans = 0;
for(int i = 1; i <= s; i++) {
mylist.add(sc.nextInt());
}
for(int i = 0; i < mylist.size(); i++) {
Collections.sort(mylist);
System.out.print(mylist.get(i));
System.out.print(" ");
}
}

Half actual code half pseudo code, hope it helps.
input // the array that holds all numbers than the user input
int n = input.length();
ArrayList<Integer> combinations = new ArrayList<Integer>();
int totalSum = input.sum(); // sum of all the values the user input
ArrayList<Integer> allSums = new ArrayList<Ingeter>();
for(int i = 0; i < n; i++){
combinations = combine(i) // find all possible combinations of i integers in the input array; you can surely find code for retrieving combinations in another thread
foreach combination in combinations{
allSums.add(totalSum - combination.sum())
}
combinations = new ArrayList<Integer>(); // clear the combinations arraylist
}
return allSums; //all possible sums
minDistanceToNumber = absolute(allSums.get(0) - 1000); // define a function "int absolute(int value)" which will multiply value by -1 if it is less than 0 and return it or just return it if it is bigger than 0
minNumber = allSums.get(0); // this will hold the number which has the minimum distance to 1000, as in the example above
for each sum in allSums
if(absolute(sum - 1000) < minDistanceToNumber){
minDistanceToNumber = absolute(sum - 1000);
minNumber = sum;
}
}
return minNumber;

Related

Drawing six random numbers without repetition on table /java

Hello I have with repetitions in drawing randoms. I tried to do this on tables but every time I have problem with comparing generated random number with numbers in table. Be carefull there because this code now is endless loop what is throwing ArrayIndexOutOfBoundsException. Do you have any ideas? To show you what I want to get is similar to polish TV show Lotto where they are drawing 6 random numbers written on balls without repetition.
I have seen topic where it was done on lists but it's possible on tables like that?
public static void main(String[] args) {
Lotto lot = new Lotto();
int[] table = new int[6];
Random random = new Random();
for(int i = 0; i < 6; i++) {
int numbers = random.nextInt(48) + 1;
for(int k = 0; k < 6; k++) {
if (table[k] != numbers) {
try {
table[i] = numbers;
} catch (ArrayIndexOutOfBoundsException e){
System.out.println(e);
}
} else {
i--;
}
}
}
Arrays.sort(table);
for (int m = 0; m < 6; m++) {
System.out.println(table[m]);
}
}
I suggest following approach:
// Get list of all number
List<Integer> all = new ArrayList<>();
for (int i = 1; i <= 48; i++) {
all.add(i);
}
//Shuffle it
Collections.shuffle(all);
//Take first 6
List<Integer> result = all.subList(0, 6);
There are two popular techniques, choose only items that are available or choose any possible and check if it has been chose. This answer chooses from possible numbers, check if the number has been chosen already. If it has not been chosen, it is added to the array. If it has been chosen, then the process is repeated.
for(int i = 0; i < 6; i++) {
boolean selected = false;
while(!selected){
selected = true;
int numbers = random.nextInt(48) + 1;
for(int k = 0; k <= i; k++) {
if (table[k] == numbers) {
selected = false;
break;
}
}
if(selected){
table[i] = numbers;
}
}
}
The usage for the techniques depends on how many samples you need compared to the population you are choosing from.
If you need to choose any six numbers between 1 and 1000000, then this technique will work better because the odds of repeating are small, but shuffling a million element list takes more calculations.
The other technique is more appropriate say if your possible numbers are small, for example if you had to pick 6 numbers between 1 and 7, then you would pick a lot of duplicates. So shuffling a list will be better.
In your range, 6 out of 49, the choose and repeat will be faster because most often you'll find a new number.
I would do it like this:
TreeSet<Integer> t = new TreeSet<>();
while (t.size()<6) {
t.add((int)(Math.random()*48+1));
}
TreeSet guarantees that only unique items will be put into target collection.
Try and model the real world and get your application to do what happens in real life. You have 48 balls, numbered 1 to 48. Let's make a collection of them:
List<Integer> ballsInTheMachine = new ArrayList<>(48);
for (int i = 1; i <= 48; i++)
ballsInTheMachine.add(i);
Using Java 8 Streams, you can also create the same list in a way that is supposedly more succinct:
List<Integer> ballsInTheMachine = IntStream.rangeClosed(1, 48)
.collect(ArrayList::new, ArrayList::add, ArrayList::addAll);
Next, you pick 6 balls at random out of the 48:
Random rng = new Random();
List<Integer> ballsPicked = new ArrayList<>(6);
for (int i = 1; i <= 6; i++) {
int index = rng.nextInt(ballsInTheMachine.size());
Integer pickedBall = ballsInTheMachine.remove(index);
ballsPicked.add(pickedBall);
}
And now you have your 6 randomly chosen balls in the list ballsPicked.

How to re-arrange the number [duplicate]

This question already has answers here:
Maximum number that can be formed from the given digits
(2 answers)
Closed 7 years ago.
I have a number which I need to re-arrange to find the largest number. As an example input number is 355 so for this number I need to find the largest number which can be formed by re-arranging the digits. So for 355, various combination can be possible after re-arranging -
355, 535 and 553
So here 553 is the largest number and that's what I need to return. Basically given an input, I need to find the largest number which can be formed by re-arranging the numbers.
How should I go ahead and solve this problem?
So far I am able to do shuffle the numbers like this:
public static void main(String[] args) {
//generate random number
int number = 355;
//put each digit in an element of a list
List<Character> numberList = new ArrayList<Character>();
for (char c : String.valueOf(number).toCharArray()) {
numberList.add(c);
}
//shuffle
Collections.shuffle(numberList);
//output
String shuffledNumber = "";
for (Character c : numberList) {
shuffledNumber += c;
}
System.out.println(shuffledNumber);
}
But I am confuse how can I find the largest number given an input after rearranging the numbers.
If you need to rearrange the numbers so that, if we read it from left to write, it should be largest number among all the arrangements,
then it's simple, you just need to sort the number in descending order.
Try this code :
public static void main(String args[]) {
//generate random number
int number = 355;
String numStr = number + "";
char[] numCharArr = numStr.toCharArray();
int[] numArr = new int[numStr.length()];
for(int i = 0 ; i < numCharArr.length ; i ++) {
numArr[i] = Integer.parseInt(numCharArr[i] + "");
}
// Sort in descending order
for(int i = 0 ; i < numArr.length ; i ++) {
for(int j = 0 ; j < i ; j ++) {
if(numArr[i] > numArr[j]) {
// swap
int temp = numArr[i];
numArr[i] = numArr[j];
numArr[j] = temp;
}
}
}
String largestNumber = "";
for(int i : numArr) {
largestNumber += i;
}
System.out.println("The largest number is : " + largestNumber);
}
Unless you actually need to create all the combinations, I wouldn't bother.
You can actually do it using arithmetic, but in this case it's probably easier in terms of strings
naive algorithm:
source number = number.toString()
target number = ""
While source number is not empty
d = remove biggest number from source number
target number += d
You can then convert target number back to an int if required.
Another approach would be count the number of 9s and append that many 9s to the result. Repeat for 8s, then 7s, then 6s...

How to get get rid of duplicate values in an int array?

The question is as the title says, how would I get rid of duplicate values in an integer array? I want to have it so the user inputs five numbers, all ranging between 10 and 100. The catch is that I have to have it so that if the value they are inputting has already been input into the array it will not count. Here is the code I have so far:
public static void main(String[]args){
Scanner input = new Scanner(System.in);
int[] intArray = new int[5]; //max of 5 values
for(int i = 0; i < 5; i++){
System.out.println("Please enter your desired number that is between 10 and 100: ");
intArray[i] = input.nextInt(); //puts the value into the array
}
System.out.println(Arrays.toString(intArray)); //for test purposes to make sure the array was correctly taking in the values
}
}
System.out.println(Arrays.toString(intArray)); //for test purposes to make sure the array was correctly taking in the values
I am confused on how I would make it so if the user inputs a number that already exists in the array it will just not add it. Here is an example of what I mean, say the user inputs the numbers 15, 22, 46, 46, 77 once the program is done looping five times it will print out the following: [15, 22, 46, 77]. I am stuck on how to do this. Also I have edited out the if the number is between 10 and 100 if statements for it to be easier to read, and get to the main point at hand.
What about using a Set? A LinkedHashSet, in particular, allows you to do this in O(n) time and memory, while retaining the order of the inputs. And before you say "But I can't use a HashSet," you'll need its behavior for the optimal solution, so the followup question might be "How would I implement a LinkedHashSet, possibly baking the logic into my program?"
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
Set<Integer> intSet = new LinkedHashSet<>();
int[] intArray = new int[5]; //max of 5 values
for (int i = 0; i < 5; i++) {
System.out.println("Please enter your desired number that is between 10 and 100: ");
intSet.add(input.nextInt());
}
int[] intArray = new int[intSet.size()];
int i = 0;
for (Integer val : intSet) {
intArray[i++] = val;
}
}
You're saying you want a variable number of numbers at the end, so an array is not the right choice here, use an ArrayList instead.
Something like:
List<Integer> intList = new ArrayList<Integer>();
int maxElements = 5; //Set max value here
for(int i = 0; i < maxElements ; i++)
{
System.out.println("Please enter your desired number that is between 10 and 100: ");
Integer newNumber = input.nextInt();
if(newNumber >= 10 && newNumber <= 100)
{
Boolean found = false;
foreach (Integer check : intList)
{
if (check == newNumber)
{
found = true;
break;
}
}
if (!found) intList.Add(newNumber);
}
else if(newNumber < 10 || newNumber > 100)
{
System.out.println("Enter a valid number next time, this number will not be counted in the results.");
}
}
Duplicate check: that inner loop I added checks if there is another element with the same value, and in that case skips the number as you said.
I wrote this without a computer, so I could have mixed some stuff up, but you get the general idea.
If you just have to select unique numbers from the numbers that a user will input, don't store them in an Array initially.
Instead, store them in a HashMap/Hashtable and then once the user input is finished convert it to an Array.
Another way of doing this would be to use the Set Collection. Add each number you receive to an instance of the Set and finally convert the Set to an Array. Set will maintain uniqueness by default.
public static void main(String[]args){
Scanner input = new Scanner(System.in);
int[] intArray = new int[5]; //max of 5 values
Set<Integer> uniques = new HashSet<Integer>();
for(int i = 0; i < 5; i++){
System.out.println("Please enter your desired number that is between 10 and 100: ");
uniques.add(input.nextInt()); //puts the value in the set
}
System.out.println(Arrays.toString(uniques.toArray())); //for test purposes to make sure the array was correctly taking in the values
}
A one liner would accomplish what you want:
Set<Integer> noDuplicates = new LinkedHashSet<>(Arrays.asList(intArray));
Do this after you read the values and store them in your intArray.
If you want to preserve the order in which the values were entered, use a LinkedHashSet, otherwise use just a HashSet.
A Set is a collection that cannot have duplicates.
make your array size 100 and using input as a index. before update array[input] = input, check the value of the index (input number) of the array.
use a map store input values as a key. before save the value in array, check whether key is in a map or not.

How to generate 6 different random numbers in java

I want to generate 6 different random numbers by using Math.random and store them into an array.
How can I make sure that they are different? I know I need to use for-loop to check the array but how...
This is the range. I only need numbers between 1 and 49.
( 1 + (int) (Math.random() * 49) )
In Java 8:
final int[] ints = new Random().ints(1, 50).distinct().limit(6).toArray();
In Java 7:
public static void main(final String[] args) throws Exception {
final Random random = new Random();
final Set<Integer> intSet = new HashSet<>();
while (intSet.size() < 6) {
intSet.add(random.nextInt(49) + 1);
}
final int[] ints = new int[intSet.size()];
final Iterator<Integer> iter = intSet.iterator();
for (int i = 0; iter.hasNext(); ++i) {
ints[i] = iter.next();
}
System.out.println(Arrays.toString(ints));
}
Just a little messier. Not helped by the fact that it's pretty tedious to unbox the Set<Integer> into an int[].
It should be noted that this solution should be fine of the number of required values is significantly smaller than the range. As 1..49 is quite a lot larger than 6 you're fine. Otherwise performance rapidly degrades.
Create a list containing the numbers 1 to 49.
Create a random number x between 0 and the size of the list, take the number being at index x in the list, and remove it from the list.
Repeat the previous step 5 times. And you're done. Note that java.util.Random has a nextInt(int max) method that you should use instead of Math.random().
Note regarding performance: this solution has an advantage compared to the "try until you get 6 different numbers" various solutions: it runs in a O(n) time. It doesn't matter much for 6 unique numbers out of 50, but if you want to get 48 or 49 unique random numbers out of 50, you'll start seeing a difference, because you might have to generate many random numbers before getting one that isn't already in the set.
EDIT:
to reduce the cost induced by the removal of the elements in the list, you could instead simply replace the element at index x with the last element of the list (and at the second iteration, with the element at size - 2, etc.)
You can use a Set.
Set<Integer> s = new HashSet<>();
while(s.size() != 6){
s.add(1 + (int) (Math.random() * 49));
}
Integer[] arr = s.toArray(new Integer[s.size()]);
This is enough to do this in your case because the number of distinct random numbers is relatively small compared to the size of the range you generate them.
Otherwise I would go with #JBNizet approach.
Generate any 6 numbers (not necessarily different). Order them.
a1 <= a2 <= a3 <= a4 <= a5 <= a6
Now take these 6 numbers
a1 < a2 + 1 < a3 + 2 < a4 + 3 < a5 + 4 < a6 + 5
These 6 are different and random.
The idea of this construct comes from some combinatorial proofs.
Its advantage is that it's simple, fast, and deterministic.
I think the time complexity is O(count*log(count)).
I wonder if it can be improved.
import java.util.TreeMap;
public class Test005 {
public static void main(String[] args) {
int count = 6;
int min = 1;
int max = 49;
// random number mapped to the count of its occurrences
TreeMap<Integer, Integer> mp = new TreeMap<Integer, Integer>();
for (int i=0; i<count; i++){
int d = ( min + (int) (Math.random() * (max-count+1)) );
if (!mp.containsKey(d)){
mp.put(d, 0);
}
mp.put(d, mp.get(d) + 1);
}
// now ensure the output numbers are different
int j = 0;
for (int num : mp.keySet()){
int cnt = mp.get(num);
for (int i=0; i<cnt; i++){
System.out.println(num + j);
j++;
}
}
}
}
I've just came up with a small idea for Java 8-.
Set<Integer> set = new LinkedHashSet<>();
while(set.size() != 6)
set.add(rnd.nextInt(49) + 1);
Instead of checking that the array has no duplicates, you can use a bit more smartness while generating the numbers, such that uniqueness is enforced at the outset.
Create a boolean[] as long as your range (49 entries);
generate a random number from the full range;
put that number into your output array;
"cross out" the corresponding index in the boolean[];
now generate another random number, but curtail the range by one (now 48);
instead of directly using that number as output, scan your boolean[], counting all the non-crossed entries. Stop when you reach the count equal to the random number generated in step 5. The number corresponding to that entry is your output number;
go to step 4.
in your case n=6
public static int[] chooseAny(int n){
int[] lottery = new int[n];
int[] chooseFrom = new int[49];
for(int i=1 ; i <= 49 ; i++)
chooseFrom[i-1] = i;
Random rand = new Random();
int N = 49;
int index;
for(int i=0 ; i < n ; i++){
//pick random index
index = rand.nextInt(N);
lottery[i] = chooseFrom[index];
chooseFrom[index] = chooseFrom[N-1];
N--;
}
return lottery;
}
Just keep generating numbers and adding them to the array as long as they are unique; psuedocode:
num = genNextRand()
For (array length)
If (num not in array)
addToArray()
Repeat while length not equal 6
Create a variable last; initialize it to 0.
Next, in a loop x from 0 to 5, create a random number between last+1 and 49-6+x. Store this number in a list, and set last to the number generated this way.
You will end up with an ordered list of 6 random numbers in the range of 1..49 with no repeats.
That code generate numbers from 6 to 0 and save in ArrayList.
If generated number was duplicated the program generate numbers again.
If generated number is different that number is added.
Code:
private ArrayList<Integer> arraylist = new ArrayList<Integer>();
private Random rand = new Random();
public void insertNumber() {
while (true) {
int i = generateNumber();
if(!isGenerateNumberExists(i)){
addNumber(i);
break;
}
}
}
//Generate numbers
private int generateNumber() {
return rand.nextInt(6);
}
//Confirm if that number exists
private boolean isGenerateNumberExists(int y) {
for (int num : arraylist) {
if (num == y) {
return true;
}
}
return false;
}
//Add number to arrayList
private void addNumber(int x) {
arraylist.add(x);
}

Numbers I can get by adding an array in java

I need to get a minimum number that I cant get by adding different numbers of an array. Basically if I have these numbers:1,1,1,5; I can get 1,2,3,5,6... but I cant get 4 so that is the number I am looking for. Now this is my code:
import java.util.Scanner;
public class Broj_6 {
public static void main(String[] args) {
Scanner unos = new Scanner(System.in);
int k;
int n = unos.nextInt();
int niz []= new int [n];
for(int i = 0;i<n;i++){
niz[i]=unos.nextInt();
}
BubbleSort(niz);
for(int i = 0;i<n;i++){
System.out.print(niz[i] + " ");
}
for(int br = 1;br<=10000;br++){
for(k = 1;k<n;k++){
if(niz[k]>br){
break;
}
}
int podniz [] = new int [k];
for(int i=0;i<podniz.length;i++){
niz[i] = podniz[i];
}
//This is where I will need my logic to go
}
}
static void BubbleSort (int [] niz){
int pom;
for(int i = 0;i<niz.length-1;i++){
for(int j = 0;j<niz.length-1-i;j++){
if(niz[j]>niz[j+1]){
pom = niz[j];
niz[j] = niz[j+1];
niz[j+1] = pom;
}
}
}
}
}
So the code goes by testing each number individually from 1 to 100000 and makes a subarray of all numbers given that are less than the number itself. Now here is the problem,I dont know how to mix and match the numbers in the subarray so it can get(or not get) the desired number. When every combination is tested and there is no desired number,I will break; the loop and print i. Just to clarify,I can only use addition,and each number can only go in once
You can achieve this as below:
Use two nested loops, like below to calculate the sum of different numbers:
List<Integer> additionList = new ArrayList<Integer>();
int []inputNumbers = .... // Logic to read inputs
for(int _firstIndex = 0; _firstIndex < totalInputs; _firstIndex++){
for(int _secondIndex = _firstIndex + 1; _secondIndex < totalInputs; _secondIndex++){
additionList.add(inputNumbers[_firstIndex]); // only because you have 1 in the sample output
additionList.add(inputNumbers[_firstIndex] + inputNumbers[_secondIndex ]);
}
}
Then sort additionList and look for any missing entry. The first missing entry will be your answer,
Sorting the whole array and then finding sum of all subarrays does solve the problem, but is costly: O(2n^2) ~ O(n^2).
More efficient way to solve this will be Kadane's Algorithm: http://en.wikipedia.org/wiki/Maximum_subarray_problem
What the algo does:
Start from first element and increase the array size (sub array) till you reach the sum you're desiring.
my_num = 1;
while(true){
if(sum_subarray) > my_num){
current position = new subarray;
}
and this subarray concept is calculated through Kadane's approach:
def sum_subarray(A):
sum_ending_here = sum_so_far = 0
for x in A:
sum_ending_here = max(0, max_ending_here + x)
sum_so_far = max(sum_so_far, sum_ending_here)
return sum_so_far
I couldn't solve the problem completely. 'my_num' mentioned here needs to be incremented from 1, and break when my_num > max_sum. I hope someone can add to it and make it compilable.
Note:
This will also take care if negative elements are present in array.

Categories