What algorithm can I use to produce 'Random' value? - algorithm

Say I have 4 possible results and the probabilities of each result appearing are
1 = 10%
2 = 20%
3 = 30%
4 = 40%
I'd like to write a method like GetRandomValue which if called 1000 times would return
1 x 100 times
2 x 200 times
3 x 300 times
4 x 400 times
Whats the name of an algorithm which would produce such results?

in your case you can generate a random number (int) within 1..10 and if it's 1 then select 1, if it's between 2-3 select 2 and if it's between 4..6 select 3 and if is between 7..10 select 4.
In all if you have some probabilities which sum to 1, you can have a random number within (0,1) distribute your generated result to related value (I simplified in your case within 1..10).

To get a random number you would use the Random class of .Net.
Something like the following would accomplish what you requested:
public class MyRandom
{
private Random m_rand = new Random();
public int GetNextValue()
{
// Gets a random value between 0-9 with equal probability
// and converts it to a number between 1-4 with the probablities requested.
switch (m_rand.Next(0, 9))
{
case 0:
return 1;
case 1: case 2:
return 2;
case 3: case 4: case 5:
return 3;
default:
return 4;
}
}
}

If you just want those probabilities in the long run, you can just get values by randomly selecting one element from the array {1,2,2,3,3,3,4,4,4,4}.
If you however need to retrieve exactly 1000 elements, in those specific quantities, you can try something like this (not C#, but shouldn't be a problem):
import java.util.Random;
import java.util.*;
class Thing{
Random r = new Random();
ArrayList<Integer> numbers=new ArrayList<Integer>();
ArrayList<Integer> counts=new ArrayList<Integer>();
int totalCount;
public void set(int i, int count){
numbers.add(i);
counts.add(count);
totalCount+=count;
}
public int getValue(){
if (totalCount==0)
throw new IllegalStateException();
double pos = r.nextDouble();
double z = 0;
int index = 0;
//we select elements using their remaining counts for probabilities
for (; index<counts.size(); index++){
z += counts.get(index) / ((double)totalCount);
if (pos<z)
break;
}
int result = numbers.get(index);
counts.set( index , counts.get(index)-1);
if (counts.get(index)==0){
counts.remove(index);
numbers.remove(index);
}
totalCount--;
return result;
}
}
class Test{
public static void main(String []args){
Thing t = new Thing(){{
set(1,100);
set(2,200);
set(3,300);
set(4,400);
}};
int[]hist=new int[4];
for (int i=0;i<1000;i++){
int value = t.getValue();
System.out.print(value);
hist[value-1]++;
}
System.out.println();
double sum=0;
for (int i=0;i<4;i++) sum+=hist[i];
for (int i=0;i<4;i++)
System.out.printf("%d: %d values, %f%%\n",i+1,hist[i], (100*hist[i]/sum));
}
}

Related

Special numbers challenge in programming

First, sorry for my bad English.
Special numbers are numbers that the sum of the digits is divisible to the number of the digit.
Example: 135 is a special number because the sum of the digits is 1+3+5 = 9, the number of the digit is 3, and 9 is divisible to 3 because 9 % 3 == 0. 2,3,9,13,17,15,225, 14825 are also special numbers.
Requirement:
Write a program that read the number n (n <= 10^6) from a file named SNUMS.INP (SNUMS.INP can contain up to 10^6 numbers) and print the result out into the file SNUMS.OUT. Number n is the order of the special number and the result will be that special number in n order (sorry I don't know how to express it).
Example: n = 3 means you have to print out the 3rd special number which is 3, n = 10 you have to print out 10th special number which is 11, n = 13 you have to print out 13th special number which is 17, n = 15 you have to print out 15th special number which is 20.
The example bellow will demonstrate the file SNUMS.INP and SNUMS.OUT (Remember: SNUMS.INP can contain up to 10^6 numbers)
SNUMS.INP:
2
14
17
22
SNUMS.OUT:
2
19
24
35
I have my own alogrithm but the the running time exceeds 1 second (my SNUMS.INP has 10^6 numbers). So I need the optimal alogrithm so that the running time will be less than or equal 1s.
Guys I decide to post my own code which is written in Java, it always take more than 4 seconds to run. Could you guys please suggest some ideas to improve or how to make it run faster
import java.util.Scanner;
import java.io.*;
public class Test
{
public static void main(String[]args) throws IOException
{
File file = new File("SNUMS.INP");
Scanner inputFile = new Scanner(file);
int order = 1;
int i = 1;
int[] special = new int[1000000+1];
// Write all 10^6 special numbers into an array named "special"
while (order <= 1000000)
{
if (specialNumber(i) == true)
{
special[order] = i;
order++;
}
i++;
}
// Write the result to file
PrintWriter outputFile = new PrintWriter("SNUMS.OUT");
outputFile.println(special[inputFile.nextInt()]);
while (inputFile.hasNext())
outputFile.println(special[inputFile.nextInt()]);
outputFile.close();
}
public static boolean specialNumber(int i)
{
// This method check whether the number is a special number
boolean specialNumber = false;
byte count=0;
long sum=0;
while (i != 0)
{
sum = sum + (i % 10);
count++;
i = i / 10;
}
if (sum % count == 0) return true;
else return false;
}
}
This is file SNUMS.INP (sample) contains 10^6 numbers if you guys want to test.
https://drive.google.com/file/d/0BwOJpa2dAZlUNkE3YmMwZmlBOTg/view?usp=sharing
I've managed to solve it in 0.6 seconds on C# 6.0 (.Net 4.6 IA-64) at Core i7 3.2 GHz with HDD 7200 rpc; hope that precompution will be fast enough at your workstation:
// Precompute beautiful numbers
private static int[] BeautifulNumbers(int length) {
int[] result = new int[length];
int index = 0;
for (int i = 1; ; ++i) {
int sum = 0;
int count = 0;
for (int v = i; v > 0; sum += v % 10, ++count, v /= 10)
;
if (sum % count == 0) {
result[index] = i;
if (++index >= result.Length)
return result;
}
}
}
...
// Test file with 1e6 items
File.WriteAllLines(#"D:\SNUMS.INP", Enumerable
.Range(1, 1000000)
.Select(index => index.ToString()));
...
Stopwatch sw = new Stopwatch();
sw.Start();
// Precomputed numbers (about 0.3 seconds to be created)
int[] data = BeautifulNumbers(1000000);
// File (about 0.3 seconds for both reading and writing)
var result = File
.ReadLines(#"D:\SNUMS.INP")
.Select(line => data[int.Parse(line) - 1].ToString());
File.WriteAllLines(#"D:\SNUMS.OUT", result);
sw.Stop();
Console.Write("Elapsed time {0}", sw.ElapsedMilliseconds);
The output vary from
Elapsed time 516
to
Elapsed time 660
with average elapsed time at about 580 milliseconds
Now that you have the metaphor of abacus implemented below, here are some hints
instead of just incrementing with 1 inside a cycle, can we incremente more aggressively? Indeed we can, but with an extra bit of care.
first, how much aggressive we can be? Looking to 11 (first special with 2 digits), it doesn't pay to just increment by 1, we can increment it by 2. Looking to 102 (special with 3 digits), we can increment it by 3. Is it natural to think we should use increments equal with the number of digits?
now the "extra bit of care" - whenever the "increment by the number of digits" causes a "carry", the naive increment breaks. Because the carry will add 1 to the sum of digits, so that we may need to subtract that one from something to keep the sum of digits well behaved.
one of the issues in the above is that we jumped quite happily at "first special with N digits", but the computer is not us to see it at a glance. Fortunately, the "first special with N digits" is easy to compute: it is 10^(N-1)+(N-1) - 10^(N-1) brings an 1 and the rest is zero, and N-1 brings the rest to make the sum of digits be the first divisible with N. Of course, this will break down if N > 10, but fortunately the problem is limited to 10^6 special numbers, which will require at most 7 digits (the millionth specual number is 6806035 - 7 digits);
so, we can detect the "first special number with N digits" and we know we should try with care to increment it by N. Can we look now better into that "extra care"?.
The code - twice as speedy as the previous one and totally "orthodox" in obtaining the data (via getters instead of direct access to data members).
Feel free to inline:
import java.util.ArrayList;
import java.util.Arrays;
public class Abacus {
static protected int pow10[]=
{1,10,100,1000, 10000, 100000, 1000000, 10000000, 100000000}
;
// the value stored for line[i] corresponds to digit[i]*pow10[i]
protected int lineValues[];
protected int sumDigits;
protected int representedNumber;
public Abacus() {
this.lineValues=new int[0];
this.sumDigits=0;
this.representedNumber=0;
}
public int getLineValue(int line) {
return this.lineValues[line];
}
public void clearUnitLine() {
this.sumDigits-=this.lineValues[0];
this.representedNumber-=this.lineValues[0];
this.lineValues[0]=0;
}
// This is how you operate the abacus in real life being asked
// to add a number of units to the line presenting powers of 10
public boolean addWithCarry(int units, int line) {
if(line-1==pow10.length) {
// don't have enough pow10 stored
pow10=Arrays.copyOf(pow10, pow10.length+1);
pow10[line]=pow10[line-1]*10;
}
if(line>=this.lineValues.length) {
// don't have enough lines for the carry
this.lineValues=Arrays.copyOf(this.lineValues, line+1);
}
int digitOnTheLine=this.lineValues[line]/pow10[line];
int carryOnTheNextLine=0;
while(digitOnTheLine+units>=10) {
carryOnTheNextLine++;
units-=10;
}
if(carryOnTheNextLine>0) {
// we have a carry, the sumDigits will be affected
// 1. the next two statememts are equiv with "set a value of zero on the line"
this.sumDigits-=digitOnTheLine;
this.representedNumber-=this.lineValues[line];
// this is the new value of the digit to set on the line
digitOnTheLine+=units;
// 3. set that value and keep all the values synchronized
this.sumDigits+=digitOnTheLine;
this.lineValues[line]=digitOnTheLine*pow10[line];
this.representedNumber+=this.lineValues[line];
// 4. as we had a carry, the next line will be affected as well.
this.addWithCarry(carryOnTheNextLine, line+1);
}
else { // we an simply add the provided value without carry
int delta=units*pow10[line];
this.lineValues[line]+=delta;
this.representedNumber+=delta;
this.sumDigits+=units;
}
return carryOnTheNextLine>0;
}
public int getSumDigits() {
return this.sumDigits;
}
public int getRepresentedNumber() {
return this.representedNumber;
}
public int getLinesCount() {
return this.lineValues.length;
}
static public ArrayList<Integer> specials(int N) {
ArrayList<Integer> ret=new ArrayList<>(N);
Abacus abacus=new Abacus();
ret.add(1);
abacus.addWithCarry(1, 0); // to have something to add to
int increment=abacus.getLinesCount();
while(ret.size()<N) {
boolean hadCarry=abacus.addWithCarry(increment, 0);
if(hadCarry) {
// need to resynch the sum for a perfect number
int newIncrement=abacus.getLinesCount();
abacus.clearUnitLine();
if(newIncrement!=increment) {
// we switched powers of 10
abacus.addWithCarry(newIncrement-1, 0);
increment=newIncrement;
}
else { // simple carry
int digitsSum=abacus.getSumDigits();
// how much we should add to the last digit to make the sumDigits
// divisible again with the increment?
int units=increment-digitsSum % increment;
if(units<increment) {
abacus.addWithCarry(units, 0);
}
}
}
ret.add(abacus.getRepresentedNumber());
}
return ret;
}
// to understand how the addWithCarry works, try the following code
static void add13To90() {
Abacus abacus; // starts with a represented number of 0
// line==1 means units of 10^1
abacus.addWithCary(9, 1); // so this should make the abacus store 90
System.out.println(abacus.getRepresentedNumber());
// line==0 means units of 10^0
abacus.addWithCarry(13, 0);
System.out.println(abacus.getRepresentedNumber()); // 103
}
static public void main(String[] args) {
int count=1000000;
long t1=System.nanoTime();
ArrayList<Integer> s1=Abacus.specials(count);
long t2=System.nanoTime();
System.out.println("t:"+(t2-t1));
}
}
Constructing the numbers from their digits is bound to be faster.
Remember the abacus? Ever used one?
import java.util.ArrayList;
public class Specials {
static public ArrayList<Integer> computeNSpecials(int N) {
ArrayList<Integer> specials = new ArrayList<>();
int abacus[] = new int[0]; // at index i we have the digit for 10^i
// This way, when we don't have enough specials,
// we simply reallocate the array and continue
while (specials.size() < N) {
// see if a carry operation is necessary
int currDigit = 0;
for (; currDigit < abacus.length && abacus[currDigit] == 9; currDigit++) {
abacus[currDigit] = 0; // a carry occurs when adding 1
}
if (currDigit == abacus.length) {
// a carry, but we don't have enough lines on the abacus
abacus = new int[abacus.length + 1];
abacus[currDigit] = 1; // we resolved the carry, all the digits below
// are 0
} else {
abacus[currDigit]++; // we resolve the carry (if there was one),
currDigit = 0; // now it's safe to continue incrementing at 10^0
}
// let's obtain the current number and the sum of the digits
int sumDigits = 0;
for (int i = 0; i<abacus.length; i++) {
sumDigits += abacus[i];
}
// is it special?
if (sumDigits % abacus.length == 0) {
// only now compute the number and collect it as special
int number = 0;
for (int i = abacus.length - 1; i >= 0; i--) {
number = 10 * number + abacus[i];
}
specials.add(number);
}
}
return specials;
}
static public void main(String[] args) {
ArrayList<Integer> specials=Specials.computeNSpecials(100);
for(int i=0; i<specials.size(); i++) {
System.out.println(specials.get(i));
}
}
}

Dividing B cheese cakes among N classes to minimize maximum no of students per cake

There is a school in a village. It has N classes. One fine day, someone donated B blue berry cheese cakes to schools. Now you need to divide these cakes such that:
Each class gets at least 1 cake.
Each class will share the cake(s) among students.
Your aim is to minimize the maximum number of students per cake in any class.
input
contains two space separated integers N and B denoting the number of classes and total number of blue berry cheese cakes, respectively.
Next N lines contain number of students in each class.
Output
For each test case, output the maximum number of students who will share a cake.
Constraints
2 <= N <= 5*10^5
N <= B <= 2*10^6 1 <= number of students in ith class <= 5*10^6
Sample Input - 1 1 2 35 Sample Output - 1 18 Sample Input - 2 2 7 20 50 Sample Output - 2 10
Apply binary search to find minimum number of students/cake.
Take lower limit 'l' as 1 and upper limit 'u' as max number of students in any given class.
Let 'mid' represents current students/cake where mid=(l+u)/2, then,
calculate required number of cakes 'req' for each mid value,
if req<=total number of cakes u=mid-1 else l=mid+1.
Apply the binary search.
Handle the case when n>b separately.
Link to my C++ code for this problem : https://ideone.com/zsTHC5
#include<bits/stdc++.h>
using namespace std;
#define ll long long
int main()
{
ll n,b;cin>>n>>b;
ll arr[n],ans=0;
for(ll i=0;i<n;i++){cin>>arr[i];ans=max(ans,arr[i]);}
if(n>b)cout<<"-1";
else if(n==b)cout<<ans;
else // binary search to find minimum students/cake
{
ll l=1,r=ans,mid; // mid represents current number of students/cake
while(l<=r)
{
mid=(l+r)/2;
ll ct=0;
for(ll i=0;i<n;i++)
{
ct+=(arr[i]+mid-1)/mid;
}
if(ct<=b)
{
ans=min(ans,mid);
r=mid-1;
}
else
l=mid+1;
}
cout<<ans;
}
return 0;
}
I agree with smartsn123.The solution is pretty simple ,initialize the max heap with each class with one cake and then start distributing cakes one by one.Here following the java implementation of the solution.
import java.util.*;
class Node{
private int nStu ;
private int nCake;
public Node(int nStu , int nCake ){
this.nStu = nStu;
this.nCake = nCake;
}
public int getnStu(){
return nStu;
}
public int getnCake(){
return nCake;
}
public void addCake(){
nCake++;
}
}
class CheeseCake{
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
int N = sc.nextInt();
int B = sc.nextInt();
int[] arr = new int[N];
int ext = B - N ;
MyComparator mc = new MyComparator();
PriorityQueue<Node> queue = new PriorityQueue<>(mc);
for(int i = 0 ; i < N ; i++){
//arr[i] = sc.nextInt();
int temp = sc.nextInt();
Node newNode = new Node(temp , 1);
queue.add(newNode);
}
while(ext != 0){
Node new1 = queue.poll();
new1.addCake();
queue.add(new1);
ext--;
}
Node newNode1 = queue.poll();
int fStu = newNode1.getnStu();
int fCake = newNode1.getnCake();
System.out.println((fStu+1)/2);
}
}
class MyComparator implements Comparator<Node>{
#Override
public int compare(Node n1 , Node n2){
/*arranging based on the students per cakes*/
double avg1 = n1.getnStu() / n1.getnCake();
double avg2 = n2.getnStu() / n2.getnCake();
if(avg1 > avg2){
return -1;
}
if(avg1 < avg2){
return 1;
}
return 0;
}
}

Efficient tuple search algorithm

Given a store of 3-tuples where:
All elements are numeric ex :( 1, 3, 4) (1300, 3, 15) (1300, 3, 15) …
Tuples are removed and added frequently
At any time the store is typically under 100,000 elements
All Tuples are available in memory
The application is interactive requiring 100s of searches per second.
What are the most efficient algorithms/data structures to perform wild card (*) searches such as:
(1, *, 6) (3601, *, *) (*, 1935, *)
The aim is to have a Linda like tuple space but on an application level
Well, there are only 8 possible arrangements of wildcards, so you can easily construct 6 multi-maps and a set to serve as indices: one for each arrangement of wildcards in the query. You don't need an 8th index because the query (*,*,*) trivially returns all tuples. The set is for tuples with no wildcards; only a membership test is needed in this case.
A multimap takes a key to a set. In your example, e.g., the query (1,*,6) would consult the multimap for queries of the form (X,*,Y), which takes key <X,Y> to the set of all tuples with X in the first position and Y in third. In this case, X=1 and Y=6.
With any reasonable hash-based multimap implementation, lookups ought to be very fast. Several hundred a second ought to be easy, and several thousand per second doable (with e.g a contemporary x86 CPU).
Insertions and deletions require updating the maps and set. Again this ought to be reasonably fast, though not as fast as lookups of course. Again several hundred per second ought to be doable.
With only ~10^5 tuples, this approach ought to be fine for memory as well. You can save a bit of space with tricks, e.g. keeping a single copy of each tuple in an array and storing indices in the map/set to represent both key and value. Manage array slots with a free list.
To make this concrete, here is pseudocode. I'm going to use angle brackets <a,b,c> for tuples to avoid too many parens:
# Definitions
For a query Q <k2,k1,k0> where each of k_i is either * or an integer,
Let I(Q) be a 3-digit binary number b2|b1|b0 where
b_i=0 if k_i is * and 1 if k_i is an integer.
Let N(i) be the number of 1's in the binary representation of i
Let M(i) be a multimap taking a tuple with N(i) elements to a set
of tuples with 3 elements.
Let t be a 3 element tuple. Then T(t,i) returns a new tuple with
only the elements of t in positions where i has a 1. For example
T(<1,2,3>,0) = <> and T(<1,2,3>,6) = <2,3>
Note that function T works fine on query tuples with wildcards.
# Algorithm to insert tuple T into the database:
fun insert(t)
for i = 0 to 7
add the entry T(t,i)->t to M(i)
# Algorithm to delete tuple T from the database:
fun delete(t)
for i = 0 to 7
delete the entry T(t,i)->t from M(i)
# Query algorithm
fun query(Q)
let i = I(Q)
return M(i).lookup(T(Q, i)) # lookup failure returns empty set
Note that for simplicity, I've not shown the "optimizations" for M(0) and M(7). For M(0), the algorithm above would create a multimap taking the empty tuple to the set of all 3-tuples in the database. You can avoid this merely by treating i=0 as a special case. Similarly M(7) would take each tuple to a set containing only itself.
An "optimized" version:
fun insert(t)
for i = 1 to 6
add the entry T(t,i)->t to M(i)
add t to set S
fun delete(t)
for i = 1 to 6
delete the entry T(t,i)->t from M(i)
remove t from set S
fun query(Q)
let i = I(Q)
if i = 0, return S
elsif i = 7 return if Q\in S { Q } else {}
else return M(i).lookup(T(Q, i))
Addition
For fun, a Java implementation:
package hacking;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Random;
import java.util.Scanner;
import java.util.Set;
public class Hacking {
public static void main(String [] args) {
TupleDatabase db = new TupleDatabase();
int n = 200000;
long start = System.nanoTime();
for (int i = 0; i < n; ++i) {
db.insert(db.randomTriple());
}
long stop = System.nanoTime();
double elapsedSec = (stop - start) * 1e-9;
System.out.println("Inserted " + n + " tuples in " + elapsedSec
+ " seconds (" + (elapsedSec / n * 1000.0) + "ms per insert).");
Scanner in = new Scanner(System.in);
for (;;) {
System.out.print("Query: ");
int a = in.nextInt();
int b = in.nextInt();
int c = in.nextInt();
System.out.println(db.query(new Tuple(a, b, c)));
}
}
}
class Tuple {
static final int [] N_ONES = new int[] { 0, 1, 1, 2, 1, 2, 2, 3 };
static final int STAR = -1;
final int [] vals;
Tuple(int a, int b, int c) {
vals = new int[] { a, b, c };
}
Tuple(Tuple t, int code) {
vals = new int[N_ONES[code]];
int m = 0;
for (int k = 0; k < 3; ++k) {
if (((1 << k) & code) > 0) {
vals[m++] = t.vals[k];
}
}
}
#Override
public boolean equals(Object other) {
if (other instanceof Tuple) {
Tuple triple = (Tuple) other;
return Arrays.equals(this.vals, triple.vals);
}
return false;
}
#Override
public int hashCode() {
return Arrays.hashCode(this.vals);
}
#Override
public String toString() {
return Arrays.toString(vals);
}
int code() {
int c = 0;
for (int k = 0; k < 3; k++) {
if (vals[k] != STAR) {
c |= (1 << k);
}
}
return c;
}
Set<Tuple> setOf() {
Set<Tuple> s = new HashSet<>();
s.add(this);
return s;
}
}
class Multimap extends HashMap<Tuple, Set<Tuple>> {
#Override
public Set<Tuple> get(Object key) {
Set<Tuple> r = super.get(key);
return r == null ? Collections.<Tuple>emptySet() : r;
}
void put(Tuple key, Tuple value) {
if (containsKey(key)) {
super.get(key).add(value);
} else {
super.put(key, value.setOf());
}
}
void remove(Tuple key, Tuple value) {
Set<Tuple> set = super.get(key);
set.remove(value);
if (set.isEmpty()) {
super.remove(key);
}
}
}
class TupleDatabase {
final Set<Tuple> set;
final Multimap [] maps;
TupleDatabase() {
set = new HashSet<>();
maps = new Multimap[7];
for (int i = 1; i < 7; i++) {
maps[i] = new Multimap();
}
}
void insert(Tuple t) {
set.add(t);
for (int i = 1; i < 7; i++) {
maps[i].put(new Tuple(t, i), t);
}
}
void delete(Tuple t) {
set.remove(t);
for (int i = 1; i < 7; i++) {
maps[i].remove(new Tuple(t, i), t);
}
}
Set<Tuple> query(Tuple q) {
int c = q.code();
switch (c) {
case 0: return set;
case 7: return set.contains(q) ? q.setOf() : Collections.<Tuple>emptySet();
default: return maps[c].get(new Tuple(q, c));
}
}
Random gen = new Random();
int randPositive() {
return gen.nextInt(1000);
}
Tuple randomTriple() {
return new Tuple(randPositive(), randPositive(), randPositive());
}
}
Some output:
Inserted 200000 tuples in 2.981607358 seconds (0.014908036790000002ms per insert).
Query: -1 -1 -1
[[504, 296, 987], [500, 446, 184], [499, 482, 16], [488, 823, 40], ...
Query: 500 446 -1
[[500, 446, 184], [500, 446, 762]]
Query: -1 -1 500
[[297, 56, 500], [848, 185, 500], [556, 351, 500], [779, 986, 500], [935, 279, 500], ...
If you think of the tuples like a ip address, then a radix tree (trie) type structure might work. Radix tree is used for IP discovery.
Another way maybe to calculate use bit operations and calculate a bit hash for the tuple and in your search do bit (or, and) for quick discovery.

Check if binary string can be partitioned such that each partition is a power of 5

I recently came across this question - Given a binary string, check if we can partition/split the string into 0..n parts such that each part is a power of 5. Return the minimum number of splits, if it can be done.
Examples would be:
input = "101101" - returns 1, as the string can be split once to form "101" and "101",as 101= 5^1.
input = "1111101" - returns 0, as the string itself is 5^3.
input = "100"- returns -1, as it can't be split into power(s) of 5.
I came up with this recursive algorithm:
Check if the string itself is a power of 5. if yes, return 0
Else, iterate over the string character by character, checking at every point if the number seen so far is a power of 5. If yes, add 1 to split count and check the rest of the string recursively for powers of 5 starting from step 1.
return the minimum number of splits seen so far.
I implemented the above algo in Java. I believe it works alright, but it's a straightforward recursive solution. Can this be solved using dynamic programming to improve the run time?
The code is below:
public int partition(String inp){
if(inp==null || inp.length()==0)
return 0;
return partition(inp,inp.length(),0);
}
public int partition(String inp,int len,int index){
if(len==index)
return 0;
if(isPowerOfFive(inp,index))
return 0;
long sub=0;
int count = Integer.MAX_VALUE;
for(int i=index;i<len;++i){
sub = sub*2 +(inp.charAt(i)-'0');
if(isPowerOfFive(sub))
count = Math.min(count,1+partition(inp,len,i+1));
}
return count;
}
Helper functions:
public boolean isPowerOfFive(String inp,int index){
long sub = 0;
for(int i=index;i<inp.length();++i){
sub = sub*2 +(inp.charAt(i)-'0');
}
return isPowerOfFive(sub);
}
public boolean isPowerOfFive(long val){
if(val==0)
return true;
if(val==1)
return false;
while(val>1){
if(val%5 != 0)
return false;
val = val/5;
}
return true;
}
Here is simple improvements that can be done:
Calculate all powers of 5 before start, so you could do checks faster.
Stop split input string if the number of splits is already greater than in the best split you've already done.
Here is my solution using these ideas:
public static List<String> powers = new ArrayList<String>();
public static int bestSplit = Integer.MAX_VALUE;
public static void main(String[] args) throws Exception {
// input string (5^5, 5^1, 5^10)
String inp = "110000110101101100101010000001011111001";
// calc all powers of 5 that fits in given string
for (int pow = 1; ; ++pow) {
String powStr = Long.toBinaryString((long) Math.pow(5, pow));
if (powStr.length() <= inp.length()) { // can be fit in input string
powers.add(powStr);
} else {
break;
}
}
Collections.reverse(powers); // simple heuristics, sort powers in decreasing order
// do simple recursive split
split(inp, 0, -1);
// print result
if (bestSplit == Integer.MAX_VALUE) {
System.out.println(-1);
} else {
System.out.println(bestSplit);
}
}
public static void split(String inp, int start, int depth) {
if (depth >= bestSplit) {
return; // can't do better split
}
if (start == inp.length()) { // perfect split
bestSplit = depth;
return;
}
for (String pow : powers) {
if (inp.startsWith(pow, start)) {
split(inp, start + pow.length(), depth + 1);
}
}
}
EDIT:
I also found another approach which looks like very fast one.
Calculate all powers of 5 whose string representation is shorter than input string. Save those strings in powers array.
For every string power from powers array: if power is substring of input then save its start and end indexes into the edges array (array of tuples).
Now we just need to find shortest path from index 0 to index input.length() by edges from the edges array. Every edge has the same weight, so the shortest path can be found very fast with BFS.
The number of edges in the shortest path found is exactly what you need -- minimum number of splits of the input string.
Instead of calculating all possible substrings, you can check the binary representation of the powers of 5 in search of a common pattern. Using something like:
bc <<< "obase=2; for(i = 1; i < 40; i++) 5^i"
You get:
51 = 1012
52 = 110012
53 = 11111012
54 = 10011100012
55 = 1100001101012
56 = 111101000010012
57 = 100110001001011012
58 = 10111110101111000012
59 = 1110111001101011001012
510 = 1001010100000010111110012
511 = 101110100100001110110111012
512 = 11101000110101001010010100012
513 = 10010001100001001110011100101012
514 = 1011010111100110001000001111010012
515 = 111000110101111110101001001100011012
516 = 100011100001101111001001101111110000012
517 = 10110001101000101011110000101110110001012
518 = 1101111000001011011010110011101001110110012
...
529 = 101000011000111100000111110101110011011010111001000010111110010101012
As you can see, odd powers of 5 always ends with 101 and even powers of 5 ends with the pattern 10+1 (where + means one or more occurrences).
You could put your input string in a trie and then iterate over it identifying the 10+1 pattern, once you have a match, evaluate it to check if is not a false positive.
You just have to save the value for a given string in a map. For example having if you have a string ending like this: (each letter may be a string of arbitrary size)
ABCD
You find that part A mod 5 is ok, so you try again for BCD, but find that B mod 5 is also ok, same for C and D as well as CD together. Now you should have the following results cached:
C -> 0
D -> 0
CD -> 0
BCD -> 1 # split B/CD is the best
But you're not finished with ABCD - you find that AB mod 5 is ok, so you check the resulting CD - it's already in the cache and you don't have to process it from the beginning.
In practice you just need to cache answers from partition() - either for the actual string or for the (string, start, length) tuple. Which one is better depends on how many repeating sequences you have and whether it's faster to compare the contents, or just indexes.
Given below is a solution in C++. Using dynamic programming I am considering all the possible splits and saving the best results.
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int isPowerOfFive(ll n)
{
if(n == 0) return 0;
ll temp = (ll)(log(n)/log(5));
ll t = round(pow(5,temp));
if(t == n)
{
return 1;
}
else
{
return 0;
}
}
ll solve(string s)
{
vector<ll> dp(s.length()+1);
for(int i = 1; i <= s.length(); i++)
{
dp[i] = INT_MAX;
for(int j = 1; j <= i; j++)
{
if( s[j-1] == '0')
{
continue;
}
ll num = stoll(s.substr(j-1, i-j+1), nullptr, 2);
if(isPowerOfFive(num))
{
dp[i] = min(dp[i], dp[j-1]+1);
}
}
}
if(dp[s.length()] == INT_MAX)
{
return -1;
}
else
{
return dp[s.length()];
}
}
int main()
{
string s;
cin>>s;
cout<<solve(s);
}

how to avoid number repeation by using random class in c#?

hi i am using Random class for getting random numbers but my requirement is once it generate one no that should not be repeate again pls help me.
Keep a list of the generated numbers and check this list before returning the next random.
Since you have not specified a language, I'll use C#
List<int> generated = new List<int>;
public int Next()
{
int r;
do { r = Random.Next() } while generated.Contains(r);
generated.Add(r);
return r;
}
The following C# code shows how to obtain 7 random cards with no duplicates. It is the most efficient method to use when your random number range is between 1 and 64 and are integers:
ulong Card, SevenCardHand;
int CardLoop;
const int CardsInDeck = 52;
Random RandObj = new Random(Seed);
for (CardLoop = 0; CardLoop < 7; CardLoop++)
{
do
{
Card = (1UL << RandObj.Next(CardsInDeck));
} while ((SevenCardHand & Card) != 0);
SevenCardHand |= Card;
}
If the random number range is greater than 64, then the next most efficient way to get random numbers without any duplicates is as follows from this C# code:
const int MaxNums = 1000;
int[] OutBuf = new int[MaxNums];
int MaxInt = 250000; // Reps the largest random number that should be returned.
int Loop, Val;
// Init the OutBuf with random numbers between 1 and MaxInt, which is 250,000.
BitArray BA = new BitArray(MaxInt + 1);
for (Loop = 0; Loop < MaxNums; Loop++)
{
// Avoid duplicate numbers.
for (; ; )
{
Val = RandObj.Next(MaxInt + 1);
if (BA.Get(Val))
continue;
OutBuf[Loop] = Val;
BA.Set(Val, true);
break;
}
}
The drawback with this technique is that it tends to use more memory, but it should be significantly faster than other approaches since it does not have to look through a large container each time a random number is obtained.

Resources