How can I improve the logic of the following code? The purpose is to compute the number of primes from 1 to the user input (limitNo). The program works fine except it takes a while, more than the usual 1-3 secs, to generate a result for huge numbers like 99999.
public static int countPrime(int limitNo) {
int noOfTimes = 0, noOfRounds = 0; int o = 1;
while (o <= limitNo) {
for (int i = 1; i <= o; i++) {
if (o%i == 0) {
noOfRounds++;
}
}
if (noOfRounds == 2) {
noOfTimes++;
}
noOfRounds = 0;
o++;
}
return noOfTimes;
}
The code can be improved by
Separating some of the lines to make an isPrime() method.
Changing limits of the for loop so that if the condition is met that means the number is not prime.
public static boolean isPrime(int num) {
for ( int i = 2 ; i < num ; i++ ) {
if ( num % i == 0 ) {
return false;
}
}
return true;
}
Replacing the code in the method with isPrime() and change the start int o = 2 ;.
public static int countPrime(int limitNo) {
int noOfTimes = 0;
int o = 2;
while ( o <= limitNo ) {
if ( isPrime(o) ) {
noOfTimes++;
}
o++;
}
return noOfTimes;
}
Of course, there are better and more improvements like:
for ( int i = 2 ; i <= num/2 ; i++ )
for ( int i = 2 ; i <= Math.sqrt(num) ; i++ )
I am using the Sieve of Eratosthenes algorithm to find the prime numbers in a range (from a min value to a max value). However, I cannot seem to get it to work if I include a min value.
Here is my code in Java:
protected static List<Integer> getSievePrimes(int a, int b) {
List<Integer> primeNumbers = new ArrayList();
boolean [] isComposite = new boolean [b + 1];
isComposite[1] = true;
// Mark all composite numbers
for (int i = 2; i <= b; i++) {
// for (int i = a == 1 ? 2 : a; i <= b; i++) {
if (!isComposite[i]) {
// 'i' is a prime number
//if (i >= a) {
primeNumbers.add(i);
//}
int multiple = 2;
while (i * multiple <= b) {
isComposite [i * multiple] = true;
multiple++;
}
}
}
return primeNumbers;
}
As you can see it currently only caters for the max value (b), and not the min value (a).
Question
How can I modify the method above to cater for both min and max?
public boolean isPrime( int test )
{
int k;
if( test < 2 )
return false;
else if( test == 2 )
return true;
else if( ( test > 2 ) && ( test % 2 == 0 ) )
return false;
else
{
for( k = 3; k < ( test/2 ); k += 2 )
{
if( test % k == 0 )
return false;
}
}
return true;
}
public void sieveOfEratosthenes( int first, int last )
{
boolean[ ] sieve = new boolean[ ( last - first ) + 1 ];
int count = 0;
int index = 0;
int cursor = first;
int end = last;
while( cursor <= end )
{
if( isPrime( cursor ) != sieve[ index ] )
{
System.out.println( cursor+" " );
count++;
}
cursor++;
index++;
}
cursor = first;
if( count == 0 )
System.out.println( "There are "+count+" primes from "+cursor+" to "+end+"." );
else if( count == 1 )
System.out.println( "is the "+count+" prime from "+cursor+" to "+end+"." );
else
System.out.println( "are the "+count+" primes from "+cursor+" to "+end+"." );
}
This code supposed to output the longest run on which a character in a string has a consecutive runs of itself. Though the problem is that it outputs: 8 (which should be 5 instead). I just would like to ask what seems to be the problem regarding this code.
public class Sample {
public static void main(String[] args) {
String setofletters = "aaakkcccccczz"; /* 15 */
int output = runLongestIndex(setofletters);
System.out.println("Longest run that first appeared in index:" + output);
}
public static int runLongestIndex(String setofletters) {
int ctr = 0;
int ctrstor = 0;
int ii = 0;
int output = 0;
// loops until the last character in the string
for (int i = 0; i < setofletters.length() - 1; i++) {
// checks if the letter is the same to the next
if (setofletters.charAt(i) == setofletters.charAt(i++)) {
ctr++;
ii = i++;
// loops until the letter in the index is no longer equal
while (setofletters.charAt(i) == setofletters.charAt(ii)) {
ii++;
ctr++;
}
if (ctr > ctrstor) {
output = i;
}
// storing purposes
ctrstor = ctr;
}
// resets the counter
ctr = 0;
}
return output;
}
}
UPDATE Sorry, I misunderstood your question a bit, you need to make the following changes in your code to make it work.(lines with comments)
public static int runLongestIndex(String setofletters){
int ctr = 1; // every character is repeated at least once, so you should initialize it to 1, not 0
int ctrstor = 0;
int ii = 0;
int output = 0;
for (int i = 0; i < setofletters.length() - 1; i++) {
if (i < setofletters.length() - 1 && setofletters.charAt(i) == setofletters.charAt(i+1)) { // i++ is not same as i+1
ctr++;
ii = i+1; // i++ is not same as i+1
while (setofletters.charAt(i) == setofletters.charAt(ii)) {
ii++;
ctr++;
}
if (ctr > ctrstor) {
output = i;
}
ctrstor = ctr;
}
ctr = 1; // for the same reason I mentioned above
}
return output;
}
EDIT : the easiest way to write your code is :
public static int runLongestIndex(String setofletters){
int ctr = 1;
int output = 0;
int j=0;
for(int i=0; i<setofletters.length()-1;i++){
j=i;
while(i <setofletters.length()-1 && setofletters.charAt(i)==setofletters.charAt(i+1)){
i++;
ctr++;
}
if(ctr>output){
output=j;
}
ctr = 1;
}
return output;
}
Why are you assigning i to output? You should assign ctr to output.
change
if(ctr>ctrstor){
output=i;
}
to
if(ctr>ctrstor){
output=ctr;
}
and also I think you should change
if(setofletters.charAt(i)==setofletters.charAt(i++))
to
if(i<setofletters.length()-1 && setofletters.charAt(i)==setofletters.charAt(i+1)){
and you should intialize ctr to 1 but not 0 because every character is repeated at least once.
I'll give you a Scala implementation for that problem.
Here it is the automatic test (in BDD style with ScalaTest)
import org.scalatest._
class RichStringSpec extends FlatSpec with MustMatchers {
"A rich string" should "find the longest run of consecutive characters" in {
import Example._
"abceedd".longestRun mustBe Set("ee", "dd")
"aeebceeedd".longestRun mustBe Set("eee")
"aaaaaaa".longestRun mustBe Set("aaaaaaa")
"abcdefgh".longestRun mustBe empty
}
}
Following is the imperative style implementation, with nested loops and mutable variables as you would normally choose to do in Java or C++:
object Example {
implicit class RichString(string: String) {
def longestRun: Set[String] = {
val chunks = mutable.Set.empty[String]
val ilen = string.length
var gmax = 0
for ((ch, curr) <- string.zipWithIndex) {
val chunk = mutable.ListBuffer(ch)
var next = curr + 1
while (next < ilen && string(next) == ch) {
chunk += string(next)
next = next + 1
}
gmax = chunk.length max gmax
if (gmax > 1) chunks += chunk.mkString
}
chunks.toSet.filter( _.length == gmax )
}
}
}
Following is a functional-style implementation, hence no variables, no loops but tail recursion with result accumulators and pattern matching to compare each character with the next one (Crazy! Isn't it?):
object Example {
implicit class RichString(string: String) {
def longestRun: Set[String] = {
def recurse(chars: String, chunk: mutable.ListBuffer[Char], chunks: mutable.Set[String]): Set[String] = {
chars.toList match {
case List(x, y, _*) if (x == y) =>
recurse(
chars.tail,
if (chunk.isEmpty) chunk ++= List(x, y) else chunk += y,
chunks
)
case Nil =>
// terminate recursion
chunks.toSet
case _ => // x != y
recurse(
chars.tail,
chunk = mutable.ListBuffer(),
chunks += chunk.mkString
)
}
}
val chunks = recurse(string, mutable.ListBuffer(), mutable.Set.empty[String])
val max = chunks.map(_.length).max
if (max > 0) chunks.filter( _.length == max ) else Set()
}
}
}
For example, for the given "aeebceeedd" string, both implementations above will build the following set of chunks (repeating characters)
Set("ee", "eee", "dd")
and they will filter those chunks having the maximum length (resulting "eee").
This code should work for any length of string sequence.
public class LongestStringSequqnce {
static String myString = "aaaabbbbcccchhhhiiiiibbbbbbbbbccccccc";
static int largestSequence = 0;
static char longestChar = '\0';
public static void main(String args[]) {
int currentSequence = 1;
char current = '\0';
char next = '\0';
for (int i = 0; i < myString.length() - 1; i++) {
current = myString.charAt(i);
next = myString.charAt(i + 1);
// If character's are in sequence , increase the counter
if (current == next) {
currentSequence += 1;
} else {
if (currentSequence > largestSequence) { // When sequence is
// completed, check if
// it is longest
largestSequence = currentSequence;
longestChar = current;
}
currentSequence = 1; // re-initialize counter
}
}
if (currentSequence > largestSequence) { // Check if last string
// sequence is longest
largestSequence = currentSequence;
longestChar = current;
}
System.out.println("Longest character sequence is of character "
+ longestChar + " and is " + largestSequence + " long");
}
}
Source : http://www.5balloons.info/program-java-code-to-find-longest-character-sequence-in-a-random-string/
if(ctr>ctrstor){
output=i;
}
//storing purposes
ctrstor=ctr;
This looks like the problem. So if you find 8 consecutive characters, it will set output to 8, and proceed. The next time thru, it finds 3 consecutive characters, so doesn't set output, but sets ctrstor. Next time thru it finds 4 consecutive characters, and this will set output to 4
There are few traps in the code that your logic felt in:
Code incorrectly assumes that there is always next character to compare current one.
This fails for string like "a" or the last character in any string.
Code does not store the max count of characters but only the max index (i).
MaxCount is needed to compare the next chars sequence size.
Loop for and loop while repeat the same subset of characters.
Also variable name style makes it harder to understand the code.
After correcting above
public static int runLongestIndex(String setofletters) {
int maxCount = 0;
int maxIndex = 0;
// loops each character in the string
for (int i = 0; i < setofletters.length() - 1; ) {
// new char sequence starts here
char currChar = setofletters.charAt(i);
int count = 1;
int index = i;
while ( (index < setofletters.length() - 1) &&
(currChar == setofletters.charAt(++index)) ) {
count++;
}
if (count > maxCount) {
maxIndex = i;
maxCount = count;
}
i = index;
}
return maxIndex;
}
See Java DEMO
I think you don't need an internal loop:
public static int runLongestIndex(String setofletters) {
if (setofletters == null || setofletters.isEmpty()) {
return -1;
}
int cnt = 1;
char prevC = setofletters.charAt(0);
int maxCnt = 1;
//char maxC = prevC;
int maxRunIdx = 0;
int curRunIdx = 0;
for (int i = 1; i < setofletters.length(); i++){
final char c = setofletters.charAt(i);
if (prevC == c) {
cnt++;
} else {
if (cnt > maxCnt) {
maxCnt = cnt;
//maxC = prevC;
maxRunIdx = curRunIdx;
}
cnt = 1;
curRunIdx = i;
}
prevC = c;
}
if (setofletters.charAt(setofletters.length() - 1) == prevC) {
if (cnt > maxCnt) {
//maxC = prevC;
maxCnt = cnt;
maxRunIdx = curRunIdx;
}
}
return maxRunIdx;
}
and this code:
System.out.println(runLongestIndex("aaakkcccccczz"));
gives you
5
This is how a "colleague" of mine is understanding to write readable code in order to solve this problem, even if this is working :)
public static int count (String str) {
int i = 0;
while(i < str.length()-1 && str.charAt(i)==str.charAt(i+1))
i ++;
return ++i;
}
public static int getLongestIndex(String str){
int output = 0;
for(int i=0, cnt = 1, counter = 0 ; i<str.length() - 1;i += cnt, cnt = count(str.substring(i)), output = (counter = (cnt > counter ? cnt : counter)) == cnt ? i : output);
return output;
}
int indexOfLongestRun(String str) {
char[] ar = str.toCharArray();
int longestRun = 0;
int lastLongestRun = 0;
int index = 0;
for(int i = ar.length-1; i>0; i--){
if(ar[i] == ar[i-1]){
longestRun++;
}else{
if(longestRun > lastLongestRun){
lastLongestRun = longestRun;
longestRun = 0;
index = i;
}
}
}
return index;
Well, the solution a bit depends on the additional requirements. Here is the code which returns the FIRST longest sequence of a repeated character int the given string, meaning if you have a second sequence with the same length you never get it out :(. But still, this is a simple and clear solution here, so good news - it works! :)
string = 'abbbccddddddddeehhhfffzzzzzzzzdddvyy'
longest_sequence = ''
for i in range(len(string)):
is_sequence = True
ch_sequence = ''
while is_sequence:
ch_sequence += string[i]
if i+1 < len(string) and string[i]==string[i+1]:
i += 1
else:
is_sequence = False
if len(ch_sequence) > len(longest_sequence):
longest_sequence = ch_sequence
print (longest_sequence)
#Paolo Angioletti already provided an answer using Scala, but it's more complicated than it needs to be. The idea is not very different from Run-length encoding. Time complexity O(n).
def longestConsecutive(s: String): (Char, Int) = {
Iterator.iterate(('\u0000', 0, 0)) { case (ch, longestRun, i) =>
val run = (i until s.length)
.takeWhile(s(_) == s(i))
.size
if (run > longestRun) (s(i), run, i + run)
else (ch, longestRun, i + run)
}
.dropWhile(i => s.isDefinedAt(i._3))
.take(1)
.map(x => (x._1, x._2))
.next()
}
Tested with:
("s", "ch", "n")
----------------
("", '\u0000', 0),
("a", 'a', 1),
("aabcddbbbea", 'b', 3),
("abcddbbb", 'b', 3),
("cbccca", 'c', 3)
#include <iostream>
#include<algorithm>
using namespace std;
int main() {
string s="abbcccccbbffffffffff";
//cin>>s;
int count=1;
int maxcount=1;
int start=0;
int ps=0;
for (int i=0;i<s.size()-1;i++)
{
if(s.at(i)==s.at(i+1))
{
count +=1;
maxcount=max(maxcount,count);
}
else
{
ps=max(ps,start+count);
count =1;
start=i;
}
}
for(int i=1;i<=maxcount;i++)
{
cout<<s.at(i+ps);
}
// your code goes here
return 0;
}
This is the simplest I can think of and it will print the number of the longest sequenced identical characters in a one line string.
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String s = scanner.nextLine();
scanner.close();
int count = 0;
int curCount = 1;
for (int i = 0; i < s.length() -1; i++) {
if (s.charAt(i) == s.charAt(i + 1)) {
curCount++;
if (curCount > count) {
count = curCount;
}
}else {
if (curCount > count) {
count = curCount;
}
curCount = 1;
}
}
System.out.println(count);
}
I want to make a list of 3 values of the following kind (binary notation!):
0;0;0
1;0;0
0;1;0
11;0;0
10;1;0
.
.
.
1111111111;0;0
0;1111111111;0
0;0;1111111111
and all missing values in between
this list means: all columns have to have all values(permutations?), but only if the bit is not set in another column
this is the problem of putting 10 markable things into 3 different boxes
i tried 3 loops but i always mess it up :(
thats what i have so far:
import java.io.FileNotFoundException;
import java.math.BigInteger;
public class create_referencevalues {
/**
* #param args
*/
public static void main(String[] args) {
Long[] list = { 10L, 40L, 90L, 160L, 250L, 350L, 500L, 650L,800L,1000L };
try {
java.io.PrintStream p = new java.io.PrintStream(
new java.io.BufferedOutputStream(
new java.io.FileOutputStream(new java.io.File(
"C:/users/djdeejay/listall.csv"), false)));
for (Integer i = 0; i < 1024; i++) {
Long sum1 = 0L;
for (Integer j = 0; j < 10; j++) {
if (BigInteger.valueOf(i).testBit(j)) {
sum1 += (list[j]);
}
}
sum1 *= Integer.bitCount(i);
Long sum2 = 0L;
for (int j = 0; j < 10; j++) {
if (BigInteger.valueOf(1023 - i).testBit(j)) {
sum2 += (list[j]);
}
}
sum2 *= 10-Integer.bitCount(i);
p.println(i +";"+ Long.toBinaryString(i)+";" + sum1+";"+ Long.toBinaryString(1023-i)+";"+sum2);
}
p.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}
how do i integrate a loop wich gives me the 3rd row and all permutations between the rows ?
thanks for any help
Try this :
public class Permutation {
private static final int NB_DIGITS = 10;
private int[] DIGIT_NUMBER = {1,10,100,1000,10000,100000,1000000,10000000,100000000, 1000000000};
public void dump(PrintStream printStream) {
int[] counter = new int[NB_DIGITS];
Arrays.fill(counter, 0);
do {
int column1 = 0;
int column2 = 0;
int column3 = 0;
for (int i = 0; i < NB_DIGITS; i++) {
int columnIdx = counter[i];
switch (columnIdx) {
case 0 : column1+=DIGIT_NUMBER[i];break;
case 1 : column2+=DIGIT_NUMBER[i];break;
case 2 : column3+=DIGIT_NUMBER[i];break;
default:
assert false;
}
}
printStream.format("%d;%d;%d%n", column1, column2, column3);
} while (increase(counter));
}
public boolean increase(int[] counter) {
int idx = 0;
while (idx < counter.length && counter[idx] == 2) {
counter[idx] = 0;
idx++;
}
if (idx == counter.length) {
return false;
}
counter[idx]++;
return true;
}
public static void main(String[] args) {
new Permutation().dump(System.out);
}
}
The counter array contains the column index where to put your digits. This is actually a loop by hand in base 3 between 0 and 3^10-1 so you reach all the possible positions.
I found this solution:
loop all three rows by all values and mask values you dont want:
if (((k & j) == 0) && ((k & i) == 0) && ((j & i) == 0) && (k^j^i)==max)
that means: a bit at a position must be set only in one row and the rows together must have set all bits
package com.djdeejay.cowTrade.client.standaloneplayer.application;
import java.io.FileNotFoundException;
import java.math.BigInteger;
public class create_referencevalues {
/**
* #param args
*/
public static void main(String[] args) {
Long[] list = { 10L, 40L, 90L, 160L, 250L, 350L, 500L, 650L, 800L,
1000L };
try {
java.io.PrintStream p = new java.io.PrintStream(
new java.io.BufferedOutputStream(
new java.io.FileOutputStream(new java.io.File(
"C:/users/djdeejay/listall.csv"), false)));
Long i = 0l;
Long j = 0l;
Long k = 0l;
Long max = 1023L;
Long count = 0l;
for (i = 0l; i < max; i++) {
for (j = 0l; j < max; j++) {
for (k = 0l; k < max; k++) {
String col1 = Long.toBinaryString(i);
String col2 = Long.toBinaryString(j);
String col3 = Long.toBinaryString(k);
if (((k & j) == 0) && ((k & i) == 0)
&& ((j & i) == 0) && (k^j^i)==max) {
count++;
Long sum1 = 0L, sum2 = 0L, sum3 = 0L;
for (int x = 0; x < 10; x++) {
if (BigInteger.valueOf(i).testBit(x)) {
sum1 += (list[x]);
}
if (BigInteger.valueOf(j).testBit(x)) {
sum2 += (list[x]);
}
if (BigInteger.valueOf(k).testBit(x)) {
sum3 += (list[x]);
}
}
sum1 *= Long.bitCount(i);
sum2 *= Long.bitCount(j);
sum3 *= Long.bitCount(k);
p.println(count + ";" + i + ";" + j + ";" + k);
System.out.println(count + ";" + col1 + ";" + col2 + ";" + col3);
}
}
}
}
System.out.println(count + ";" + i + ";" + j + ";" + k);
p.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}
So my Problem is i have to list the prime factors of a number inside an Array and the power of that prime factor in another one on the same positions inside their given array(so if you want the primefactors of 60 i would need to return an array with contents like this: primes: {2, 3, 5} powers {2, 1, 1} => (2*2)*(3*1)*(5*1) = 60.
I now have the following code to determine the duplicates inside the primes Array but how can i now instead of printing them to the console save them in another variable to then use them for the powers Array?
long current = primes[0];
boolean found = false;
for( int i = 0; i < primes.length; i++) {
if( current == primes[i] && !found) {
found = true;
}
else if( current != primes[i] ) {
System.out.print(" " + current);
current = primes[i];
found = false;
}
The full code would then be:
public class Algebra {
public static long [][] primfaktorzerlegung(long n){
int position = 0;
long[] primes = new long [0];
long [] powers = new long [0];
while(n%2 == 0) {
primes[position] = 2;
position++;
n = n / 2;
}
for (int i = 3; i <= Math.sqrt(n); i+= 2)
{
while (n%i == 0)
{
n /= i;
}
}
long current = primes[0];
boolean found = false;
for (int i = 0; i < primes.length; i++) {
if (current == primes[i] && !found) {
found = true;
} else if (current != primes[i]) {
current = primes[i];
found = false;
}
}
long[][] z = {primes,powers};
return z;
}
}
It's obviously unfinished but to show the whole thing i post it anyways.
You want the frequency of each prime, and there’s a standard way to do this in java. Also, since you don’t know how many primes there will be you’re better to use a List.
But you don’t even need to use either of those, just use a Map<Long, Long> and accumulate both primes and powers in one pass:
Map<Long, Long> primePowers = new LinkedHashMap<>();
for (int i = 2; i <= Math.sqrt(n); i+= 2) {
while (n%i == 0) {
primePowers.put(i, primePowers.getOrDefault(i, 0L) + 1);
n /= i;
}
}
// convert the Map to the return value
long[] primes, powers = new long[primePowers.size()];
int i = 0;
for (Map.Entry<Long, Long> entry : primePowers.entrySet()) {
primes[i] = entry.getKey();
powers[i] = entry.getValue();
}
return new long[][]{primes,powers};
FYI a LinkedHashMap iterates over its entries in insert order.
As a design point, the return type long[][] is not a good choice. Any situation where 2 arrays must agree on their elements aligning is poor design.
Code:
import java.util.ArrayList;
import java.util.List;
public class Primes {
static long getPowerOf( long power, long n, List<Long> primes, List<Long> powers ) {
if(( n % power ) == 0 ) {
long count = 0L;
while(( n % power ) == 0 ) {
++count;
n = n / power;
}
primes.add( power );
powers.add( count );
}
return n;
}
static long[][] getPrimes( long n ) throws Exception {
final List<Long> primes = new ArrayList<>();
final List<Long> powers = new ArrayList<>();
n = getPowerOf( 2, n, primes, powers );
for( long i = 3; n > 1; i += 2 ) {
n = getPowerOf( i, n, primes, powers );
}
if( n > 1 ) {
throw new Exception( "More primes needed" );
}
final long[][] result = new long[2][];
result[0] = new long[primes.size()];
result[1] = new long[powers.size()];
for( int i = 0; i < primes.size(); ++i ) {
result[0][i] = primes.get( i );
}
for( int i = 0; i < powers.size(); ++i ) {
result[1][i] = powers.get( i );
}
return result;
}
static void showPrimes( long[] primes, long[] powers ) {
boolean tail = false;
for( int i = 0; i < primes.length; ++i ) {
if( powers[i] > 0 ) {
if( tail ) {
System.out.print( " + " );
}
else {
tail = true;
}
System.out.print( primes[i] + "x" + powers[i]);
}
}
System.out.println();
}
public static void main( String[] args ) throws Exception {
final long[][] result = getPrimes( 2*2*3*5*5*7*23*23*23 );
showPrimes( result[0], result[1] );
}
}
Output:
2x2 + 3x1 + 5x2 + 7x1 + 23x3
Notes:
Using a class in place of long[][] for primes and powers will be better, like this:
class PrimeUsage {
long prime;
long power;
}
PrimeUsage[] or List<PrimeUsage> or Set<PrimeUsage>