I have a program that is supposed to decrypt a number to its primes. The primes also have an order: for instance, 2 is the 1st prime number, 3 is the second 5 is the third and so on. The indexes are 1 is for a, two is for b, three is for c and so on. I don't know how to compare the two array lists in order to assign an index to each prime so I can decode a word which is encrypted in the number 72216017. The number 72216017 has the primes 17,19,47,67,71. If 2,3,5,7,11... are a,b,c,d,e... these five prime numbers make up the word ghost, I just don't know how to assign and sort these numbers by their index.
package name;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class PrimeFactorsEffective {
private static int z;
private int w = z;
public static List<Integer> primeFactors(int numbers) {
int n = numbers;
List<Integer> factors = new ArrayList<Integer>();
for (int i = 2; i <= n / i; i++) {
while (n % i == 0) {
factors.add(i);
n /= i;
}
if (n > 1) {
factors.add(n);
System.out.println(factors);
z = Collections.max(factors);
}
}
return factors;
}
public static void main(String[] args) {
System.out.println("Primefactors of 72216017");
for (Integer integer : primeFactors(72216017)) {
System.out.println(integer);
}
List<Integer> factors1 = new ArrayList<Integer>();
List<String> index1 = new ArrayList<String>();
int i;
int element = 0;
int num = 0;
int maxCheck = z; // maxCheck limit till which you want to find prime numbers
boolean isPrime = true;
String primeNumbersFound = "";
//Start loop 1 to maxCheck
for (i = 1; i <= maxCheck; i++) {
isPrime = CheckPrime(i);
if (isPrime) {
primeNumbersFound = primeNumbersFound + i + " ";
factors1.add(i);
factors1.get(num);
}
}
System.out.println("Prime numbers from 1 to " + maxCheck + " are:");
System.out.println(factors1);
}
public static boolean CheckPrime(int numberToCheck) {
int remainder;
for (int i = 2; i <= numberToCheck / 2; i++) {
remainder = numberToCheck % i;
if (remainder == 0) {
return false;
}
}
return true;
}
}
You can store the primes in a List (primes in this list will be in increasing order). Now you can use Collections.BinarySearch to get the index of the prime for which you wan to find the corresponding alphabet. Once you got the index (index here according to you starts from 1, so a's index is 1, b's index is 2, c's index is 3 and so on) you can do simply something like char currentCharacter = (char) ('a' + primeIndex - 1) and the variable currentCharacter will store the alphabet corresponding to primeIndex.
Some other minor things that I'd like to suggest:
Which checking whether a number is prime or not, you can simply check upto square-root of numberToCheck. So you can replace your loop for (int i = 2; i <= numberToCheck / 2; i++) to for (int i = 2; i*i <= numberToCheck; i++). Note that It is not a good idea to calculate square-root using Math.sqrt, instead you can have a condition like i*i <= numberToCheck.
Please refrain from naming your packages that seem to be random.
As of Java SE 7 explicit type-arguments while initializing the list are not required. You can replace List<Integer> factors1 = new ArrayList<Integer>() with List<Integer> factors1 = new ArrayList<>(). Please read this for more information.
Your factor method don't really look good to me, it don't give correct results. Please see the following method that gives correct result:
{{
public static List<Integer> primeFactors(int numbers) {
int n = numbers;
List<Integer> factors = new ArrayList<>();
for (int i = 2; n>1; i++) {
while (n % i == 0) {
factors.add(i);
n /= i;
}
}
z = Collections.max(factors);
return factors;
}
Related
So I started a method which is supposed to give me an array filled with random non repeating values, that additionally are odd.
However, I only get the array filled with somewhat wrong values:
public static int[] Array(int n, int max) {
int [] arr = new int [n];
int newnum;
Random rn = new Random();
for(int i = 0; i < arr.length; i++){
newnum = rn.nextInt(0,max);
for(int j = 0; j < i; j++){
while(newnum == arr[j] && newnum % 2 == 0){
newnum = rn.nextInt(0, max);
}
}
arr[i] = newnum;
}
return arr;
}
The issue here is this:
You go through all the numbers already in the list and you reroll your number if it's equal to j. However, once you have done the comparison, your new number could be equal to arr[j-1], you don't re-check. You need to start over every time there is a match.
It should be || and not && in your condition. You want to reroll if the number is equal to a previous number OR if it is even.
The optimisation also is terrible but I guess that's not what you asked.
Fixed version (but not optimized):
public static int[] array(int n, int max) {
int[] arr = new int[n];
int newnum;
Random rn = new Random();
for (int i = 0; i < arr.length; i++) {
newnum = rn.nextInt(max);
for (int j = 0; j < i; j++) {
if (newnum == arr[j] || newnum % 2 == 0) {
//or instead of and
//we are also using if here
//because we are already re-running the loop by starting over from j = 0
newnum = rn.nextInt(max);
j = 0;
}
}
arr[i] = newnum;
}
return arr;
}
There are much better ways to do this using java features but I imagine you are still in school and they didn't teach them yet.
You should make sure that you lay your code out so that you understand it.
You should make sure that your conditions are correct at all times, and don't hesitate to delegate complexity to other methods.
public static int[] array(int n, int max) {
int[] arr = new int[n];
Random rn = new Random();
for (int i = 0; i < arr.length; i++) {
int candidate = rn.nextInt(max);
while (candidate % 2 == 0 || isContainedIn(candidate, arr, i - 1)) {
candidate = rn.nextInt(max);
}
arr[i] = candidate;
}
return arr;
}
private static boolean isContainedIn(int candidate, int[] arr, int index) {
for (int i = 0; i <= index; i++) {
if (arr[i] == candidate) {
return true;
}
}
return false;
}
An alternative is to use streams:
public static int[] array(int n, int max) {
max /= 2; // Divide by two to avoid generating twice the expected numbers.
if (n > max) throw new IllegalArgumentException("Impossible to generate such an array");
int[] array = new Random().ints(0, max) // Generate ints between 0 and half max
.map(i -> i * 2 + 1) // Make sure they're odds
.distinct() // Make sure they don't repeat
.limit(n) // Take n of those numbers
.toArray(); // Put them in an array
return array;
}
Why not create a set and keep adding till you have n elements?
You want non-repeating odd numbers in a range. For non-repeating numbers you are better off using a shuffle for a small range or a set for a large range.
For picking odd numbers it might be easier to pick integers from half the range and use num = 2 * pick + 1 so as to not generate any even numbers, though you will need to be careful about setting the correct range of integers for the initial pick.
As Janardhan Maithil suggested you could utilize a set for the destinctveness
But you also have to take into account what should happen if one would try to get more values, than are available.
public static int[] randomDistinctiveOdds(int maxAmount, int maxValue) {
if (maxAmount / 2 > maxValue) {
throw new IllegalArgumentException("Not enough distinct odd values in the range from 0 to " + maxValue);
}
Random random = new Random();
Set<Integer> result = new HashSet<>(maxAmount);
int nextInt;
while (result.size() < maxAmount) {
if ((nextInt = random.nextInt(maxValue)) % 2 == 1)
result.add(nextInt);
}
return result.stream().mapToInt(Integer::intValue).toArray();
}
or a solution with streams
public static int[] randomDistinctiveOddsWithStreams(int maxAmount, int maxValue) {
if (maxAmount / 2 > maxValue) {
throw new IllegalArgumentException("Not enough distinct odd values in the range from 0 to " + maxValue);
}
List<Integer> odds = IntStream.range(0, maxValue)
.boxed()
.filter(i -> i % 2 == 1) // only odds
.collect(Collectors.toList());
Collections.shuffle(odds);
return odds.stream()
.mapToInt(Integer::intValue)
.limit(maxAmount) // take at most maxAmount
.toArray();
}
I have an array and i want to find number with most divisor. The problem is that i can find the number but i cant print how many divisor it is.
static void printDivisors(int n)
{
for (int i=1;i<=n;i++)
if (n%i==0)
System.out.print(i+" ");
}
public static void main(String args[])
{
System.out.println("The divisors of 100 are: ");
printDivisors(100);;
}
}
First of all, you only need to check values between 1 and n/2 to find the divisors of n. You won't find a divisor between n/2 and n (except for n itself). This will effectively reduce your execution time by half.
So your divisor finding method can be improved like below to count the number of divisors of a given number.
static int getNumDivisors(int n) {
int noOfDivisors = 0;
for (int i = 1; i <= n / 2; i++) {
if (n % i == 0) {
noOfDivisors++;
}
}
if (n > 1) {
noOfDivisors++; // n itself is a divisor of n
}
return noOfDivisors;
}
Then you need to iterate through the numbers array given by user and find the number of divisors for each number.
While iterating you need 2 variables
currentMaxDivisors - to store the max no of divisors you have found so far
numWithMaxDivisors - which number had the above number of divisors
If you happen to find a new number with more divisors, you update these variables with the new values. At the end, numWithMaxDivisors variable will contain the number with maximum divisors.
static int getNumDivisors(int n) {
int noOfDivisors = 0;
for (int i = 1; i <= n / 2; i++) {
if (n % i == 0) {
System.out.print(i + " ");
noOfDivisors++;
}
}
if (n > 1) {
noOfDivisors++; // n itself is a divisor of n
}
return noOfDivisors;
}
static int getNumWithMaxDivisors(int[] numbers) {
// Assuming numbers array has at least one element
int currentMaxDivisors = 0;
int numWithMaxDivisors = numbers[0];
for (int i = 0; i < numbers.length; i++) {
int numDivisors = getNumDivisors(numbers[i]);
if (numDivisors > currentMaxDivisors) {
numWithMaxDivisors = numbers[i];
}
}
return numWithMaxDivisors;
}
public static void main(String[] args) {
int[] numbers = new int[]{100, 55, 67, 2003, 12};
int numWithMaxDivisors = getNumWithMaxDivisors(numbers);
System.out.println(numWithMaxDivisors);
}
Given a number N, for example, take 1091, here the count of digits is 4 but the count of unique digits is 3 i.e. 1, 0 & 9 are unique (since 1 is repeated).
I have tried breaking the number into individual digits and adding it to ArrayList and later converting it to an array. Then, iterating through the array and increasing the count of unique digits by 1 every time I got a unique digit in the array, But I have not got the required output. Kindly someone help in finding the unique digits count in a given number in Java.
import java.util.ArrayList;
public class UniqueDigits {
static int uniqueDigitCount(int n) {
ArrayList<Integer> ar = new ArrayList<>();
int temp = n;
int count = 1;
do {
ar.add(temp % 10);
temp /= 10;
}
while (temp > 0);
Integer[] arr = new Integer[ar.size()];
arr = ar.toArray(arr);
if (arr.length > 0) {
for (int i = 0; i < arr.length - 1; i++) {
if (arr[i] != arr[i + 1]) {
count++;
}
}
return count;
} else {
return 0;
}
}
public static void main(String[] args) {
System.out.println(uniqueDigitCount(1091));
}
}
static int uniqueDigitCount(int n) {
HashSet<Integer> hs = new HashSet<Integer>();
int count;
if(n == 0)
{
count = 1;
}
else
{
while(n > 0)
{
hs.add(n % 10);
n /= 10;
}
count = hs.size();
}
return count;
}
A HashSet stores only unique elements. So, when we return the length of the HashSet after adding each digit of the input integer to it, we can obtain the count of unique digits in that input.
This could be done with a set. A set is a collection of unique elements. Putting all characters (digits) into a set will result in the duplicates being discarded. Its size() will then return the distinct elements.
Using streams:
int number = 1091;
long uniques = String.valueOf(number).chars()
.mapToObj(c -> c)
.collect(Collectors.toSet())
.size();
Or leveraging a count on the stream:
String.valueOf(number).chars()
.distinct()
.count();
import java.util.ArrayList;
import java.util.HashSet;
public class UniqueDigits {
static int uniqueDigitCount(int n) {
ArrayList<Integer> ar = new ArrayList<>();
int temp = n;
int count = 1;
do {
ar.add(temp % 10);
temp /= 10;
} while (temp > 0);
Integer[] arr = new Integer[ar.size()];
arr = ar.toArray(arr);
HashSet<Integer> hs = new HashSet<Integer>();
for (int i = 0; i < arr.length - 1; i++) {
hs.add(arr[i]);
}
return hs.size();
}
public static void main(String[] args) {
System.out.println(uniqueDigitCount(1091));
}
}
For a detailed explanation do check my article on gfg (Count of unique digits in a given number N):
import java.util.*;
class UniqueDigits {
// Function that returns the count
// of unique digits of number N
public static void
countUniqueDigits(int N)
{
// Initialize a variable to
// store count of unique digits
int res = 0;
// Initialize cnt array to
// store digit count
int cnt[] = { 0, 0, 0, 0, 0,
0, 0, 0, 0, 0 };
// Iterate through digits of N
while (N > 0) {
// Retrieve the last
// digit of N
int rem = N % 10;
// Increase the count
// of the last digit
cnt[rem]++;
// Remove the last
// digit of N
N = N / 10;
}
// Iterate through the
// cnt array
for (int i = 0;
i < cnt.length; i++) {
// If frequency of
// digit is 1
if (cnt[i] == 1) {
// Increment the count
// of unique digits
res++;
}
}
// Return the count of unique digit
System.out.println(res);
}
public static void main(String[] args)
{
// Given Number N
int N = 2234262;
// Function Call
countUniqueDigits(N);
}
}
num = Integer.parseInt(tf1.getText());
entered = Integer.parseInt(tf1.getText());
num2 = Integer.parseInt(tf2.getText());
entered2 = Integer.parseInt(tf2.getText());
for (i =(int) num; i<= num2 ; i++){
for (j=0 ; j >= i ; j++) {}
System.out.println(i);
}
do i have to use array list ? ArrayList<Integer> lists = new ArrayList<Integer>();
and if i use it how i can to separate each number in the arraylist,so I found the numbers between two numbers but how I can take each number and do the collatz conjecture java , please i need help quickly
The collatz conjecture is simple n = n/2 if n%2 == 0 and n = 3*n + 1 if n%2 == 1 and you're doing these calculations until n = 1. Based on this, you could write your function like this:
public static List<Integer> calculateConjecture(int number) {
List<Integer> values = new ArrayList<>();
while (number != 1) {
if (number % 2 == 0) {
number = number / 2;
} else {
number = 3 * number + 1;
}
values.add(number);
}
return values;
}
public static void main(String[] args) {
int inferiorLimit = 11;
int superiorLimit = 15;
for (int i = inferiorLimit; i <= superiorLimit; i++) {
System.out.println(calculateConjecture(i));
}
}
The values ArrayList will hold the sequence of numbers for the current number between the [inferiorLimit,superiorLimit]
I need to count all the divisors for every number in the range 1 to n. I have written down below an implementation for, given an integer num, it counts the number of divisors of num. Its complexity is O(sqrt(n)). So over all complexity comes out to be O(n * sqrt(n)). Can it be reduced? If YES, then can you give an algorithm for that?
CODE :
public static int countDivisors(int num)
{
int limit = (int)Math.sqrt(num);
int count = 2;
for(int i = 2 ; i <= limit ; i++)
{
if(num % i == 0)
{
count++;
if(num / i != i)
{
count++;
}
}
}
return count;
}
PS:
This function will be called n times.
You can improve upon the naive approach using kind of a generalized Sieve of Eratosthenes. Instead of just marking the number as composite also store its first divisor that you found (I do this in the function computeDivs below).
class Main
{
// using Sieve of Eratosthenes to factorize all numbers
public static int[] computeDivs(int size) {
int[] divs = new int[size + 1];
for (int i = 0; i < size + 1; ++i) {
divs[i] = 1;
}
int o = (int)Math.sqrt((double)size);
for (int i = 2; i <= size; i += 2) {
divs[i] = 2;
}
for (int i = 3; i <= size; i += 2) {
if (divs[i] != 1) {
continue;
}
divs[i] = i;
if (i <= o) {
for (int j = i * i; j < size; j += 2 * i) {
divs[j] = i;
}
}
}
return divs;
}
// Counting the divisors using the standard fomula
public static int countDivisors(int x, int[] divs) {
int result = 1;
int currentDivisor = divs[x];
int currentCount = 1;
while (currentDivisor != 1) {
x /= currentDivisor;
int newDivisor = divs[x];
if (newDivisor != currentDivisor) {
result *= currentCount + 1;
currentDivisor = newDivisor;
currentCount = 1;
} else {
currentCount++;
}
}
if (x != 1) {
result *= currentCount + 1;
}
return result;
}
public static int countAllDivisors(int upTo) {
int[] divs = computeDivs(upTo + 1);
int result = 0;
for (int i = 1; i <= upTo; ++i) {
result += countDivisors(i, divs);
}
return result;
}
public static void main (String[] args) throws java.lang.Exception {
System.out.println(countAllDivisors(15));
}
}
You can also see the code executed on ideone here.
In short I use the sieve to compute the biggest prime factor for each number. Using this I can compute the factor decomposition of every number very efficiently (and I use this in countDivisors).
It is hard to compute the complexity of the sieve but a standard estimate is O(n * log(n)). Also I am pretty confident it is not possible to improve on that complexity.
You can do much better than O(n.sqrt(n)) by using simple iteration. The code is in C++, but you can easily get the idea.
#include <iostream>
#include <vector>
using namespace std;
void CountDivisors(int n) {
vector<int> cnts(n + 1, 1);
for (int i = 2; i <= n; ++i) {
for (int j = i; j <= n; j += i) {
cnts[j]++;
}
}
for (int i = 1; i <= n; ++i) {
cout << cnts[i] << " \n"[i == n];
}
}
int main() {
CountDivisors(100);
return 0;
}
Running time is n/1 + n/2 + n/3 + n/4 + ... + n/n which can be approximated by O(nH(n)), where H(n) is the harmonic series. I think the value is not bigger than O(nlog(n)).
Using iteration is OK for relatively small numbers. As soon as the number of divisors is getting bigger (over 100-200), the iteration is going to take a significant amount of time.
A better approach would be to count the number of divisors with help of prime factorization of the number.
So, express the number with prime factorization like this:
public static List<Integer> primeFactorizationOfTheNumber(long number) {
List<Integer> primes = new ArrayList<>();
var remainder = number;
var prime = 2;
while (remainder != 1) {
if (remainder % prime == 0) {
primes.add(prime);
remainder = remainder / prime;
} else {
prime++;
}
}
return primes;
}
Next, given the prime factorization, express it in the exponent form, get exponents and add 1 to each of them. Next, multiply resulting numbers. The result will be the count of divisors of a number. More on this here.
private long numberOfDivisorsForNumber(long number) {
var exponentsOfPrimeFactorization = primeFactorizationOfTheNumber(number)
.stream()
.collect(Collectors.groupingBy(Integer::intValue, Collectors.counting()))
.values();
return exponentsOfPrimeFactorization.stream().map(n -> n + 1).reduce(1L, Math::multiplyExact);
}
This algorithm works very fast. For me, it finds a number with 500 divisors within less than a second.