How can I generate two different random numbers in dart?
I have generated two random numbers using code below.
int rand1 = Random().nextInt(16);
int rand2 = Random().nextInt(16);
if(rand1 == rand2)
// generate new random
How do I generate new random numbers until rand1 != rand2?
If you need to have two different random numbers in a fixed range, then the simplest approach would be:
var random = Random();
var n1 = random.nextInt(16);
var n2 = random.nextInt(15);
if (n2 >= n1) n2 += 1;
This ensures that the first number can assume all 16 values, and the second number can assume any of the remaining 15 values, and with as even a distribution as the random generator allows.
For two ordered distinct numbers in the range 0..15, there are 16 * 15 possible outcomes, and you probably want each outcome to be equally probable.
This code achieves this by picking the first number at random, and then picking the second number to be one of the numbers different from the first by ensuring that it is in either the range [0 .. (n1 - 1)] or the range [(n1 + 1) .. 15] ... by picking a number in the range [0 .. 14] and adding one if >= n1, shifting the range [n1 .. 14] into [(n1 + 1) .. 15].
You can do this for more numbers, but you have to do more tests and additions.
I would suggest you a different approach, looping can be pain.
// create a list say of 16 numbers.
List list = List.generate(16, (i) => i);
// shuffle it
list.shuffle();
// take the numbers now, they are always unique
int firstRandonNum = list[0];
int secondRandonNum = list[1];
This is the simplest way to do it:
import 'dart:math';
void main() {
int rand1 = Random().nextInt(16);
int rand2 = Random().nextInt(16);
while(rand1 == rand2){
rand1 = Random().nextInt(16);
rand2 = Random().nextInt(16);
}
print('$rand1 $rand2');
}
To generate any 5 unique random numbers under a range 0-49
List<int> numberList = [];
Random randomizer = new Random();
while (numberList.length < 5) {
int random_number = randomizer.nextInt(50);
if (!numberList.contains(random_number)) {
numberList.add(random_number);
}
}
A potential solution for pulling many out of many (say, 50 out of thousands) is to loop and memoize with a hash set.
I pulled this from my code, but something like:
var hashSet = HashSet();
for (var i = 0; i < boardSize; i++) {
words.add([]);
for (var j = 0; j < boardSize; j++) {
Random _random = new Random();
String wordToAdd = abstractPossibleWords[_random.nextInt(abstractPossibleWords.length)];
while (hashSet.contains(wordToAdd)) {
wordToAdd = abstractPossibleWords[_random.nextInt(abstractPossibleWords.length)];
}
words[i].add(wordToAdd);
}
}
maybe useful for you.
'max' is exclusive. the unique result number is in the return List.
List<int> getRandomNums(int countOfNum, int max) {
int num = 0;
List<int> numList = [];
var random = Random();
int i = 0;
while ( i < countOfNum) {
int oldNum = num;
num = random.nextInt(max);
if (numList.contains(num)) continue;
numList.add(num);
i++;
}
return numList;
}
Related
This is an interview question. Count all numbers with unique digits (in decimal) in the range [1, N].
The obvious solution is to test each number in the range if its digits are unique. We can also generate all numbers with unique digits (as permutations) and test if they are in the range.
Now I wonder if there is a DP (dynamic programming) solution for this problem.
I'm thinking:
Number of unique digits numbers 1-5324
= Number of unique digits numbers 1-9
+ Number of unique digits numbers 10-99
+ Number of unique digits numbers 100-999
+ Number of unique digits numbers 1000-5324
So:
f(n) = Number of unique digits numbers with length n.
f(1) = 9 (1-9)
f(2) = 9*9 (1-9 * 0-9 (excluding first digit))
f(3) = 9*9*8 (1-9 * 0-9 (excluding first digit) * 0-9 (excluding first 2 digits))
f(4) = 9*9*8*7
Add all of the above until you get to the number of digits that N has minus 1.
Then you only have to do Number of unique digits numbers 1000-5324
And:
Number of unique digits numbers 1000-5324
= Number of unique digits numbers 1000-4999
+ Number of unique digits numbers 5000-5299
+ Number of unique digits numbers 5300-5319
+ Number of unique digits numbers 5320-5324
So:
N = 5324
If N[0] = 1, there are 9*8*7 possibilities for the other digits
If N[0] = 2, there are 9*8*7 possibilities for the other digits
If N[0] = 3, there are 9*8*7 possibilities for the other digits
If N[0] = 4, there are 9*8*7 possibilities for the other digits
If N[0] = 5
If N[1] = 0, there are 8*7 possibilities for the other digits
If N[1] = 1, there are 8*7 possibilities for the other digits
If N[1] = 2, there are 8*7 possibilities for the other digits
If N[1] = 3
If N[2] = 0, there are 7 possibilities for the other digits
If N[2] = 1, there are 7 possibilities for the other digits
If N[2] = 2
If N[3] = 0, there is 1 possibility (no other digits)
If N[3] = 1, there is 1 possibility (no other digits)
If N[3] = 2, there is 1 possibility (no other digits)
If N[3] = 3, there is 1 possibility (no other digits)
The above is something like:
uniques += (N[0]-1)*9!/(9-N.length+1)!
for (int i = 1:N.length)
uniques += N[i]*(9-i)!/(9-N.length+1)!
// don't forget N
if (hasUniqueDigits(N))
uniques += 1
You don't really need DP as the above should be fast enough.
EDIT:
The above actually needs to be a little more complicated (N[2] = 2 and N[3] = 2 above is not valid). It needs to be more like:
binary used[10]
uniques += (N[0]-1)*9!/(9-N.length+1)!
used[N[0]] = 1
for (int i = 1:N.length)
uniques += (N[i]-sum(used 0 to N[i]))*(9-i)!/(9-N.length+1)!
if (used[N[i]] == 1)
break
used[N[i]] = 1
// still need to remember N
if (hasUniqueDigits(N))
uniques += 1
For an interview question like this, a brute-force algorithm is probably intended, to demonstrate logic and programming competency. But also important is demonstrating knowledge of a good tool for the job.
Sure, after lots of time spent on the calculation, you can come up with a convoluted mathematical formula to shorten a looping algorithm. But this question is a straightforward example of pattern-matching, so why not use the pattern-matching tool built in to just about any language you'll be using: regular expressions?
Here's an extremely simple solution in C# as an example:
string csv = string.Join(",", Enumerable.Range(1, N));
int numUnique = N - Regex.Matches(csv, #"(\d)\d*\1").Count;
Line 1 will differ depending on the language you use, but it's just creating a CSV of all the integers from 1 to N.
But Line 2 would be very similar no matter what language: count how many times the pattern matches in the csv.
The regex pattern matches a digit possibly followed by some other digits, followed by a duplicate of the first digit.
Lazy man's DP:
Prelude> :m +Data.List
Data.List> length [a | a <- [1..5324], length (show a) == length (nub $ show a)]
2939
Although this question had been posted in 2013, I feel like it is still worthy to provide an implementation for reference as other than the algorithm given by Dukeling I couldn't find any implementation on the internet.
I wrote the code in Java for both brute force and Dukeling's permutation algorithm and, if I'm correct, they should always yield the same results.
Hope it can help somebody trying so hard to find an actual running solution.
public class Solution {
public static void main(String[] args) {
test(uniqueDigitsBruteForce(5324), uniqueDigits(5324));
test(uniqueDigitsBruteForce(5222), uniqueDigits(5222));
test(uniqueDigitsBruteForce(5565), uniqueDigits(5565));
}
/**
* A math version method to count numbers with distinct digits.
* #param n
* #return
*/
static int uniqueDigits(int n) {
int[] used = new int[10];
String seq = String.valueOf(n);
char[] ca = seq.toCharArray();
int uniq = 0;
for (int i = 1; i <= ca.length - 1; i++) {
uniq += uniqueDigitsOfLength(i);
}
uniq += (getInt(ca[0]) - 1) * factorial(9) / factorial(9 - ca.length + 1);
used[getInt(ca[0])] = 1;
for (int i = 1; i < ca.length; i++) {
int count = 0;
for (int j = 0; j < getInt(ca[i]); j++) {
if (used[j] != 1) count++;
}
uniq += count * factorial(9 - i) / factorial(9 - ca.length + 1);
if (used[getInt(ca[i])] == 1)
break;
used[getInt(ca[i])] = 1;
}
if (isUniqueDigits(n)) {
uniq += 1;
}
return uniq;
}
/**
* A brute force version method to count numbers with distinct digits.
* #param n
* #return
*/
static int uniqueDigitsBruteForce(int n) {
int count = 0;
for (int i = 1; i <= n; i++) {
if (isUniqueDigits(i)) {
count++;
}
}
return count;
}
/**
* http://oeis.org/A073531
* #param n
* #return
*/
static int uniqueDigitsOfLength(int n) {
if (n < 1) return 0;
int count = 9;
int numOptions = 9;
while(--n > 0) {
if (numOptions == 0) {
return 0;
}
count *= numOptions;
numOptions--;
}
return count;
}
/**
* Determine if given number consists of distinct digits
* #param n
* #return
*/
static boolean isUniqueDigits(int n) {
int[] used = new int[10];
if (n < 10) return true;
while (n > 0) {
int digit = n % 10;
if (used[digit] == 1)
return false;
used[digit] = 1;
n = n / 10;
}
return true;
}
static int getInt(char c) {
return c - '0';
}
/**
* Calculate Factorial
* #param n
* #return
*/
static int factorial(int n) {
if (n > 9) return -1;
if (n < 2) return 1;
int res = 1;
for (int i = 2; i <= n; i++) {
res *= i;
}
return res;
}
static void test(int expected, int actual) {
System.out.println("Expected Result: " + expected.toString());
System.out.println("Actual Result: " + actual.toString());
System.out.println(expected.equals(actual) ? "Correct" : "Wrong Answer");
}
}
a python solution is summarized as follow :
the solution is based on the mathematical principle of Bernhard Barker provided previous in the answer list:
thanks to Bernhard's ideal
def count_num_with_DupDigits(self, n: int) -> int:
# Fill in your code for the function. Do not change the function name
# The function should return an integer.
n_str = str(n)
n_len = len(n_str)
n_unique = 0
# get the all the x000 unique digits
if n > 10:
for i in range(n_len-1):
n_unique = n_unique + 9*int(np.math.factorial(9)/np.math.factorial(10-n_len+i+1))
m=0
if m == 0:
n_first = (int(n_str[m])-1)*int(np.math.factorial(9)/np.math.factorial(10-n_len))
m=m+1
count_last=0
n_sec=0
for k in range(n_len-1):
if m == n_len-1:
count_last = int(n_str[m])+1
for l in range(int(n_str[m])+1):a
if n_str[0:n_len-1].count(str(l)) > 0:
count_last = count_last-1
else:
for s in range(int(n_str[k+1])):
if n_str[0:k+1].count(str(s))>0:
n_sec=n_sec
else:
n_sec = int(np.math.factorial(9-m)/np.math.factorial(10-n_len))+n_sec
if n_str[0:k+1].count(n_str[k+1]) > 0:
break
m= m+1
value=n-(n_sec+n_first+n_unique+count_last)
else:
value = 0
return value
import java.io.*;
import java.util.*;
import java.text.*;
import java.math.*;
import java.util.regex.*;
public class Solution {
public static void main(String[] args) {
int rem;
Scanner in=new Scanner(System.in);
int num=in.nextInt();
int length = (int)(Math.log10(num)+1);//This one is to find the length of the number i.e number of digits of a number
int arr[]=new int[length]; //Array to store the individual numbers of a digit for example 123 then we will store 1,2,3 in the array
int count=0;
int i=0;
while(num>0) //Logic to store the digits in array
{ rem=num%10;
arr[i++]=rem;
num=num/10;
}
for( i=0;i<length;i++) //Logic to find the duplicate numbers
{
for(int j=i+1;j<length;j++)
{
if(arr[i]==arr[j])
{
count++;
break;
}
}
}
//Finally total number of digits minus duplicates gives the output
System.out.println(length-count);
}
}
Here is what you want, implemented by Python
def numDistinctDigitsAtMostN(n):
nums = [int(i) for i in str(n+1)]
k = len(str(n+1))
res = 0
# Here is a paper about Number of n-digit positive integers with all digits distinct
# http://oeis.org/A073531
# a(n) = 9*9!/(10-n)!
# calculate the number of n-digit positive integers with all digits distinct
for i in range(1, k):
res += 9 * math.perm(9,i-1)
# count no duplicates for numbers with k digits and smaller than n
for i, x in enumerate(nums):
if i == 0:
digit_range = range(1,x) # first digit can not be 0
else:
digit_range = range(x)
for y in digit_range:
if y not in nums[:i]:
res += math.perm(9-i,k-1-i)
if x in nums[:i]:
break
return res
And here are some good test cases.
They are big enough to test my code.
numDistinctDigitsAtMostN(100) = 90 #(9+81)
numDistinctDigitsAtMostN(5853) = 3181
numDistinctDigitsAtMostN(5853623) = 461730
numDistinctDigitsAtMostN(585362326) = 4104810
There is an integer array d which does not contain more than two elements of the same value. How many distinct ascending triples (d[i] < d[j] < d[k], i < j < k) are present?
Input format:
The first line contains an integer N denoting the number of elements in the array. This is followed by a single line containing N integers separated by a single space with no leading/trailing spaces
Output format:
A single integer that denotes the number of distinct ascending triples present in the array
Constraints:
N <= 10^5
Every value in the array is present at most twice
Every value in the array is a 32-bit positive integer
Sample input:
6
1 1 2 2 3 4
Sample output:
4
Explanation:
The distinct triplets are
(1,2,3)
(1,2,4)
(1,3,4)
(2,3,4)
Another test case:
Input:
10
1 1 5 4 3 6 6 5 9 10
Output:
28
I tried to solve using DP. But out of 15 test cases only 7 test cases passed.
Please help solve this problem.
You should note that you only need to know the number of elements that are smaller/larger than a particular element to know how many triples it serves as the middle point for. Using this you can calculate the number of triples quite easily, the only remaining problem is to get rid of duplicates, but given that you are limited to at most 2 of the same element, this is trivial.
I solved using a Binary Index Tree http://community.topcoder.com/tc?module=Static&d1=tutorials&d2=binaryIndexedTrees.
I also did a small write up, http://www.kesannmcclean.com/?p=223.
package com.jai;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.HashMap;
public class Triplets {
int[] lSmaller, rLarger, treeArray, dscArray, lFlags, rFlags;
int size, count = 0;
Triplets(int aSize, int[] inputArray) {
size = aSize;
lSmaller = new int[size];
rLarger = new int[size];
dscArray = new int[size];
int[] tmpArray = Arrays.copyOf(inputArray, inputArray.length);
Arrays.sort(tmpArray);
HashMap<Integer, Integer> tmpMap = new HashMap<Integer, Integer>(size);
for (int i = 0; i < size; i++) {
if (!tmpMap.containsKey(tmpArray[i])) {
count++;
tmpMap.put(tmpArray[i], count);
}
}
count++;
treeArray = new int[count];
lFlags = new int[count];
rFlags = new int[count];
for (int i = 0; i < size; i++) {
dscArray[i] = tmpMap.get(inputArray[i]);
}
}
void update(int idx) {
while (idx < count) {
treeArray[idx]++;
idx += (idx & -idx);
}
}
int read(int index) {
int sum = 0;
while (index > 0) {
sum += treeArray[index];
index -= (index & -index);
}
return sum;
}
void countLeftSmaller() {
Arrays.fill(treeArray, 0);
Arrays.fill(lSmaller, 0);
Arrays.fill(lFlags, 0);
for (int i = 0; i < size; i++) {
int val = dscArray[i];
lSmaller[i] = read(val - 1);
if (lFlags[val] == 0) {
update(val);
lFlags[val] = i + 1;
} else {
lSmaller[i] -= lSmaller[lFlags[val] - 1];
}
}
}
void countRightLarger() {
Arrays.fill(treeArray, 0);
Arrays.fill(rLarger, 0);
Arrays.fill(rFlags, 0);
for (int i = size - 1; i >= 0; i--) {
int val = dscArray[i];
rLarger[i] = read(count - 1) - read(val);
if (rFlags[val] == 0) {
update(val);
rFlags[val] = i + 1;
}
}
}
long countTriplets() {
long sum = 0;
for (int i = 0; i < size; i++) {
sum += lSmaller[i] * rLarger[i];
}
return sum;
}
public static void main(String[] args) throws Exception {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int N = Integer.parseInt(br.readLine());
int[] a = new int[N];
String[] strs = br.readLine().split(" ");
for (int i = 0; i < N; i++)
a[i] = Integer.parseInt(strs[i]);
Triplets sol = new Triplets(N, a);
sol.countLeftSmaller();
sol.countRightLarger();
System.out.println(sol.countTriplets());
}
}
For tentative algorithm that I came up with, it should be:
(K-1)!^2
where K is number of unique elements.
EDIT
After more thinking about this:
SUM[i=1,K-2] SUM[j=i+1,K-1] SUM[m=j+1,K] 1
=> SUM[i=1,K-2] (SUM[j=i+1,K-1] (K-j))
if the input is not sorted (the question is not clear about this): sort it
remove the duplicated items (this step could be conbined with the first step)
now pick 3 items. Since the items are already sorted, the three chosen items are ordered as well
IIRC there are (n!) / ((n-3)! * 3!) ways to pick the three items; with n := the number of unique items
#hadron: exactly, I couldn get my head around on why it should be 28 and not 35 for a set of 7 distinct numbers *
[Since the ques is about ascending triplets, repeated numbers can be discarded].
btw, here's a very bad Java solution(N^3):
I have also printed out the possible triplets:
I'm also thinking about some function that dictates the no: of triplets possible for input 'N'
4 4
5 10
6 20
7 35
8 56
9 84
package org.HackerRank.AlgoChallenges;
import java.util.Iterator;
import java.util.Scanner;
import java.util.TreeSet;
public class Triplets {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int result = 0;
int n = scanner.nextInt();
Object[] array = new Object[n];
TreeSet<Integer> treeSet = new TreeSet<Integer>();
/*
* for (int i = 0; i < n; i++) { array[i] = scanner.nextInt(); }
*/
while (n>0) {
treeSet.add(scanner.nextInt());
n--;
}
scanner.close();
Iterator<Integer> iterator = treeSet.iterator();
int i =0;
while (iterator.hasNext()) {
//System.out.println("TreeSet["+i+"] : "+iterator.next());
array[i] = iterator.next();
//System.out.println("Array["+i+"] : "+array[i]);
i++;
}
for (int j = 0; j < (array.length-2); j++) {
for (int j2 = (j+1); j2 < array.length-1; j2++) {
for (int k = (j2+1); k < array.length; k++) {
if(array[j]!=null && array[j2]!=null && array[k]!=null){
System.out.println("{ "+array[j]+", "+array[j2]+", "+array[k]+" }");
result++;
}
}
}
}
System.out.println(result);
}
One of solution in python:
from itertools import combinations as comb
def triplet(lis):
done = dict()
result = set()
for ind, num in enumerate(lis):
if num not in done:
index = ind+1
for elm in comb(lis[index:], 2):
s,t = elm[0], elm[1]
if (num < s < t):
done.setdefault(num, None)
fin = (num,s,t)
if fin not in result:
result.add(fin)
return len(result)
test = int(raw_input())
lis = [int(_) for _ in raw_input().split()]
print triplet(lis)
Do you care about complexity?
Is the input array sorted?
if you don't mind about complexity you can solve it in complexity of N^3.
The solution with complexity N^3:
If it not sorted, then sorted the array.
Use 3 for loops one inside the other and go threw the array 3 times for each number.
Use hash map to count all the triples. The key will be the triple it self and the value will be the number of occurences.
It should be something like this:
for (i1=0; i1<N; i1++) {
for (i2=i1; i2<N; i2++) {
for (i3=i2; i3<N; i3++) {
if (N[i1] < N[i2] < N[i3]) {
/* if the triple exists in the hash then
add 1 to its value
else
put new triple to the hash with
value 1
*/
}
}
}
}
Result = number of triples in the hash;
I didn't try it but I think it should work.
I recently went through an interview and was asked this question. Let me explain the question properly:
Given a number M (N-digit integer) and K number of swap operations(a swap
operation can swap 2 digits), devise an algorithm to get the maximum
possible integer?
Examples:
M = 132 K = 1 output = 312
M = 132 K = 2 output = 321
M = 7899 k = 2 output = 9987
My solution ( algorithm in pseudo-code). I used a max-heap to get the maximum digit out of N-digits in each of the K-operations and then suitably swapping it.
for(int i = 0; i<K; i++)
{
int max_digit_currently = GetMaxFromHeap();
// The above function GetMaxFromHeap() pops out the maximum currently and deletes it from heap
int index_to_swap_with = GetRightMostOccurenceOfTheDigitObtainedAbove();
// This returns me the index of the digit obtained in the previous function
// .e.g If I have 436659 and K=2 given,
// then after K=1 I'll have 936654 and after K=2, I should have 966354 and not 963654.
// Now, the swap part comes. Here the gotcha is, say with the same above example, I have K=3.
// If I do GetMaxFromHeap() I'll get 6 when K=3, but I should not swap it,
// rather I should continue for next iteration and
// get GetMaxFromHeap() to give me 5 and then get 966534 from 966354.
if (Value_at_index_to_swap == max_digit_currently)
continue;
else
DoSwap();
}
Time complexity: O(K*( N + log_2(N) ))
// K-times [log_2(N) for popping out number from heap & N to get the rightmost index to swap with]
The above strategy fails in this example:
M = 8799 and K = 2
Following my strategy, I'll get M = 9798 after K=1 and M = 9978 after K=2. However, the maximum I can get is M = 9987 after K=2.
What did I miss?
Also suggest other ways to solve the problem & ways to optimize my solution.
I think the missing part is that, after you've performed the K swaps as in the algorithm described by the OP, you're left with some numbers that you can swap between themselves. For example, for the number 87949, after the initial algorithm we would get 99748. However, after that we can swap 7 and 8 "for free", i.e. not consuming any of the K swaps. This would mean "I'd rather not swap the 7 with the second 9 but with the first".
So, to get the max number, one would perform the algorithm described by the OP and remember the numbers which were moved to the right, and the positions to which they were moved. Then, sort these numbers in decreasing order and put them in the positions from left to right.
This is something like a separation of the algorithm in two phases - in the first one, you choose which numbers should go in the front to maximize the first K positions. Then you determine the order in which you would have swapped them with the numbers whose positions they took, so that the rest of the number is maximized as well.
Not all the details are clear, and I'm not 100% sure it handles all cases correctly, so if anyone can break it - go ahead.
This is a recursive function, which sorts the possible swap values for each (current-max) digit:
function swap2max(string, K) {
// the recursion end:
if (string.length==0 || K==0)
return string
m = getMaxDigit(string)
// an array of indices of the maxdigits to swap in the string
indices = []
// a counter for the length of that array, to determine how many chars
// from the front will be swapped
len = 0
// an array of digits to be swapped
front = []
// and the index of the last of those:
right = 0
// get those indices, in a loop with 2 conditions:
// * just run backwards through the string, until we meet the swapped range
// * no more swaps than left (K)
for (i=string.length; i-->right && len<K;)
if (m == string[i])
// omit digits that are already in the right place
while (right<=i && string[right] == m)
right++
// and when they need to be swapped
if (i>=right)
front.push(string[right++])
indices.push(i)
len++
// sort the digits to swap with
front.sort()
// and swap them
for (i=0; i<len; i++)
string.setCharAt(indices[i], front[i])
// the first len digits are the max ones
// the rest the result of calling the function on the rest of the string
return m.repeat(right) + swap2max(string.substr(right), K-len)
}
This is all pseudocode, but converts fairly easy to other languages. This solution is nonrecursive and operates in linear worst case and average case time.
You are provided with the following functions:
function k_swap(n, k1, k2):
temp = n[k1]
n[k1] = n[k2]
n[k2] = temp
int : operator[k]
// gets or sets the kth digit of an integer
property int : magnitude
// the number of digits in an integer
You could do something like the following:
int input = [some integer] // input value
int digitcounts[10] = {0, ...} // all zeroes
int digitpositions[10] = {0, ...) // all zeroes
bool filled[input.magnitude] = {false, ...) // all falses
for d = input[i = 0 => input.magnitude]:
digitcounts[d]++ // count number of occurrences of each digit
digitpositions[0] = 0;
for i = 1 => input.magnitude:
digitpositions[i] = digitpositions[i - 1] + digitcounts[i - 1] // output positions
for i = 0 => input.magnitude:
digit = input[i]
if filled[i] == true:
continue
k_swap(input, i, digitpositions[digit])
filled[digitpositions[digit]] = true
digitpositions[digit]++
I'll walk through it with the number input = 724886771
computed digitcounts:
{0, 1, 1, 0, 1, 0, 1, 3, 2, 0}
computed digitpositions:
{0, 0, 1, 2, 2, 3, 3, 4, 7, 9}
swap steps:
swap 0 with 0: 724886771, mark 0 visited
swap 1 with 4: 724876781, mark 4 visited
swap 2 with 5: 724778881, mark 5 visited
swap 3 with 3: 724778881, mark 3 visited
skip 4 (already visited)
skip 5 (already visited)
swap 6 with 2: 728776481, mark 2 visited
swap 7 with 1: 788776421, mark 1 visited
swap 8 with 6: 887776421, mark 6 visited
output number: 887776421
Edit:
This doesn't address the question correctly. If I have time later, I'll fix it but I don't right now.
How I would do it (in pseudo-c -- nothing fancy), assuming a fantasy integer array is passed where each element represents one decimal digit:
int[] sortToMaxInt(int[] M, int K) {
for (int i = 0; K > 0 && i < M.size() - 1; i++) {
if (swapDec(M, i)) K--;
}
return M;
}
bool swapDec(int[]& M, int i) {
/* no need to try and swap the value 9 as it is the
* highest possible value anyway. */
if (M[i] == 9) return false;
int max_dec = 0;
int max_idx = 0;
for (int j = i+1; j < M.size(); j++) {
if (M[j] >= max_dec) {
max_idx = j;
max_dec = M[j];
}
}
if (max_dec > M[i]) {
M.swapElements(i, max_idx);
return true;
}
return false;
}
From the top of my head so if anyone spots some fatal flaw please let me know.
Edit: based on the other answers posted here, I probably grossly misunderstood the problem. Anyone care to elaborate?
You start with max-number(M, N, 1, K).
max-number(M, N, pos, k)
{
if k == 0
return M
max-digit = 0
for i = pos to N
if M[i] > max-digit
max-digit = M[i]
if M[pos] == max-digit
return max-number(M, N, pos + 1, k)
for i = (pos + 1) to N
maxs.add(M)
if M[i] == max-digit
M2 = new M
swap(M2, i, pos)
maxs.add(max-number(M2, N, pos + 1, k - 1))
return maxs.max()
}
Here's my approach (It's not fool-proof, but covers the basic cases). First we'll need a function that extracts each DIGIT of an INT into a container:
std::shared_ptr<std::deque<int>> getDigitsOfInt(const int N)
{
int number(N);
std::shared_ptr<std::deque<int>> digitsQueue(new std::deque<int>());
while (number != 0)
{
digitsQueue->push_front(number % 10);
number /= 10;
}
return digitsQueue;
}
You obviously want to create the inverse of this, so convert such a container back to an INT:
const int getIntOfDigits(const std::shared_ptr<std::deque<int>>& digitsQueue)
{
int number(0);
for (std::deque<int>::size_type i = 0, iMAX = digitsQueue->size(); i < iMAX; ++i)
{
number = number * 10 + digitsQueue->at(i);
}
return number;
}
You also will need to find the MAX_DIGIT. It would be great to use std::max_element as it returns an iterator to the maximum element of a container, but if there are more you want the last of them. So let's implement our own max algorithm:
int getLastMaxDigitOfN(const std::shared_ptr<std::deque<int>>& digitsQueue, int startPosition)
{
assert(!digitsQueue->empty() && digitsQueue->size() > startPosition);
int maxDigitPosition(0);
int maxDigit(digitsQueue->at(startPosition));
for (std::deque<int>::size_type i = startPosition, iMAX = digitsQueue->size(); i < iMAX; ++i)
{
const int currentDigit(digitsQueue->at(i));
if (maxDigit <= currentDigit)
{
maxDigit = currentDigit;
maxDigitPosition = i;
}
}
return maxDigitPosition;
}
From here on its pretty straight what you have to do, put the right-most (last) MAX DIGITS to their places until you can swap:
const int solution(const int N, const int K)
{
std::shared_ptr<std::deque<int>> digitsOfN = getDigitsOfInt(N);
int pos(0);
int RemainingSwaps(K);
while (RemainingSwaps)
{
int lastHDPosition = getLastMaxDigitOfN(digitsOfN, pos);
if (lastHDPosition != pos)
{
std::swap<int>(digitsOfN->at(lastHDPosition), digitsOfN->at(pos));
++pos;
--RemainingSwaps;
}
}
return getIntOfDigits(digitsOfN);
}
There are unhandled corner-cases but I'll leave that up to you.
I assumed K = 2, but you can change the value!
Java code
public class Solution {
public static void main (String args[]) {
Solution d = new Solution();
System.out.println(d.solve(1234));
System.out.println(d.solve(9812));
System.out.println(d.solve(9876));
}
public int solve(int number) {
int[] array = intToArray(number);
int[] result = solve(array, array.length-1, 2);
return arrayToInt(result);
}
private int arrayToInt(int[] array) {
String s = "";
for (int i = array.length-1 ;i >= 0; i--) {
s = s + array[i]+"";
}
return Integer.parseInt(s);
}
private int[] intToArray(int number){
String s = number+"";
int[] result = new int[s.length()];
for(int i = 0 ;i < s.length() ;i++) {
result[s.length()-1-i] = Integer.parseInt(s.charAt(i)+"");
}
return result;
}
private int[] solve(int[] array, int endIndex, int num) {
if (endIndex == 0)
return array;
int size = num ;
int firstIndex = endIndex - size;
if (firstIndex < 0)
firstIndex = 0;
int biggest = findBiggestIndex(array, endIndex, firstIndex);
if (biggest!= endIndex) {
if (endIndex-biggest==num) {
while(num!=0) {
int temp = array[biggest];
array[biggest] = array[biggest+1];
array[biggest+1] = temp;
biggest++;
num--;
}
return array;
}else{
int n = endIndex-biggest;
for (int i = 0 ;i < n;i++) {
int temp = array[biggest];
array[biggest] = array[biggest+1];
array[biggest+1] = temp;
biggest++;
}
return solve(array, --biggest, firstIndex);
}
}else{
return solve(array, --endIndex, num);
}
}
private int findBiggestIndex(int[] array, int endIndex, int firstIndex) {
int result = firstIndex;
int max = array[firstIndex];
for (int i = firstIndex; i <= endIndex; i++){
if (array[i] > max){
max = array[i];
result = i;
}
}
return result;
}
}
I am given an input, "N", i have to find the number of list of length N, which starts with 1, such that the next number to be added is at most 1 more than the max number added till now. For Example,
N = 3, possible lists => (111, 112, 121, 122, 123), [113, or 131 is not possible as while adding '3' to the list, the maximum number present in the list would be '1', thus we can add only 1 or 2].
N = 4, the list 1213 is possible as while adding 3, the maximum number in the list is '2', thus 3 can be added.
Problem is to count the number of such lists possible for a given input "N".
My code is :-
public static void Main(string[] args)
{
var noOfTestCases = Convert.ToInt32(Console.ReadLine());
var listOfOutput = new List<long>();
for (int i = 0; i < noOfTestCases; i++)
{
var requiredSize = Convert.ToInt64(Console.ReadLine());
long result;
const long listCount = 1;
const long listMaxTillNow = 1;
if (requiredSize < 3)
result = requiredSize;
else
{
SeqCount.Add(requiredSize, 0);
AddElementToList(requiredSize, listCount, listMaxTillNow);
result = SeqCount[requiredSize];
}
listOfOutput.Add(result);
}
foreach (var i in listOfOutput)
{
Console.WriteLine(i);
}
}
private static Dictionary<long, long> SeqCount = new Dictionary<long, long>();
private static void AddElementToList(long requiredSize, long listCount, long listMaxTillNow)
{
if (listCount == requiredSize)
{
SeqCount[requiredSize] = SeqCount[requiredSize] + 1;
return;
}
var listMaxTillNowNew = listMaxTillNow + 1;
for(var i = listMaxTillNowNew; i > 0; i--)
{
AddElementToList(requiredSize, listCount + 1,
i == listMaxTillNowNew ? listMaxTillNowNew : listMaxTillNow);
}
return;
}
Which is the brute force method. I wish to know what might be the best algorithm for the problem?
PS : I only wish to know the number of such lists, so i am sure creating all the list won't be required. (The way i am doing in the code)
I am not at all good in algorithms, so please excuse for the long question.
This problem is a classic example of a dynamic programming problem:
If you define a function dp(k, m) to be the number of lists of length k for which the maximum number is m, then you have a recurrence relation:
dp(1, 1) = 1
dp(1, m) = 0, for m > 1
dp(k, m) = dp(k-1, m) * m + dp(k-1, m-1)
Indeed, there is only one list of length 1 and its maximum element is 1.
When you are building a list of length k with max element m, you can take any of the (k-1)-lists with max = m and append 1 or 2 or .... or m. Or you can take a (k-1)-list with max element m-1 and append m. If you take a (k-1)-list with max element less than m-1 then by your rule you can't get a max of m by appending just one element.
You can compute dp(k,m) for all k = 1,...,N and m = 1,...,N+1 using dynamic programming in O(N^2) and then the answer to your question would be
dp(N,1) + dp(N,2) + ... + dp(N,N+1)
Thus the algorithm is O(N^2).
See below for the implementation of dp calculation in C#:
int[] arr = new int[N + 2];
for (int m = 1; m < N + 2; m++)
arr[m] = 0;
arr[1] = 1;
int[] newArr = new int[N + 2];
int[] tmp;
for (int k = 1; k < N; k++)
{
for (int m = 1; m < N + 2; m++)
newArr[m] = arr[m] * m + arr[m - 1];
tmp = arr;
arr = newArr;
newArr = tmp;
}
int answer = 0;strong text
for (int m = 1; m < N + 2; m++)
answer += arr[m];
Console.WriteLine("The answer for " + N + " is " + answer);
Well, I got interrupted by a fire this afternoon (really!) but FWIW, here's my contribution:
/*
* Counts the number of possible integer list on langth N, with the
* property that no integer in a list(starting with one) may be more
* than one greater than the greatest integer preceeding it in the list.
*
* I am calling this "Semi-Factorial" since it is somewhat similar to
* the factorial function and its constituent integer combinations.
*/
public int SemiFactorial(int N)
{
int sumCounts = 0;
// get a list of the counts of all valid lists of length N,
//whose maximum integer is listCounts[maxInt].
List<int> listCounts = SemiFactorialCounts(N);
for (int maxInt = 1; maxInt <= N; maxInt++)
{
// Get the number of lists, of length N-1 whose maximum integer
//is (maxInt):
int maxIntCnt = listCounts[maxInt];
// just sum them up
sumCounts += maxIntCnt;
}
return sumCounts;
}
// Returns a list of the counts of all valid lists of length N, and
//whose maximum integer is [i], where [i] is also its index in this
//returned list. (0 is not used).
public List<int> SemiFactorialCounts(int N)
{
List<int> cnts;
if (N == 0)
{
// no valid lists,
cnts = new List<int>();
// (zero isn't used)
cnts.Add(0);
}
else if (N == 1)
{
// the only valid list is {1},
cnts = new List<int>();
// (zero isn't used)
cnts.Add(0);
//so that's one list of length 1
cnts.Add(1);
}
else
{
// start with the maxInt counts of lists whose length is N-1:
cnts = SemiFactorialCounts(N - 1);
// add an entry for (N)
cnts.Add(0);
// (reverse order because we overwrite the list using values
// from the next lower index.)
for (int K = N; K > 0; K--)
{
// The number of lists of length N and maxInt K { SF(N,K) }
// Equals K times # of lists one shorter, but same maxInt,
// Plus, the number of lists one shorter with maxInt-1.
cnts[K] = K * cnts[K] + cnts[K - 1];
}
}
return cnts;
}
pretty similar to the others. Though I wouldn't call this "classic dynamic programming" so much as just "classic recursion".
Question is:
Write a method to randomly generate a set of m integers from an array of size n. Each
element must have equal probability of being chosen.
Is this answer correct?:
I pick a first integer uniformly randomly.
pick next. if it already exists. I don't take it else take it. and continue till I have m integers.
let m be the number of elements to select
for i = 1; i <= m; i++
pick a random number from 1 to n, call it j
swap array[j] and array [n] (assuming 1 indexed arrays)
n--
At the end of the loop, the last m elements of array is your random subset. There is a variation on fisher-yates shuffle.
There are 2^n subsets. Pick a number between 0 and 2^n-1 and turn that into binary. Those with bits set should be taken from the array and stored.
e.g. Consider the set 1,2,3,4.
int[] a = new int[]{ 1, 2, 3, 4 }
int n = (2*2*2*2) - 1; // 2^n -1
int items = new Random().nextInt(n);
// If items is 3 then this is 000011 so we would select 1 and 2
// If items is 5 then this is 000101 so we would select 1 and 3
// And so on
for (int i=0;i<a.length;++i) {
if ((items & (1 << i)) != 0) {
// The bit is set, grab this item
System.out.println("Selected " + a[i]);
}
}
Think of your original range to choose from as a list from 1-n, when you choose an element (number) remove that element from the list. Choose elements based on list index, rather than the actual number value.
int Choose1(List<int> elts)
{
var idx = rnd.Next(0,elts.Count);
var elt = elts[idx];
elts.RemoveAt(idx);
return elt;
}
public List<int> Choose(int fromN, int chooseM)
{
var range = new List<int>();
for (int i = 1; i <= fromN; i++)
{
range.Add(i);
}
var choices = new List<int>();
for (int i = 0; i < chooseM; i++)
{
choices.Add(Choose1(range));
}
return choices;
}
Using lists won't be efficient for large numbers, but you can use the same approach without actually constructing any lists, using a bit of arithmetic.
If your picks are random then the probability of picking m items in the manner you described would be 1/pow(n,m). I think what you need is 1/C(n,m).