Why won't my random selection without replacement algorithm work? - for-loop

I have made a very simple algorithm that picks a set of numToPick random numbers from the range 0 to batchMax, without replacement. Then it places each selected number in an array called numsPicked. For some reason I cannot explain, it isn't working on DartPad.
import 'dart:math';
void main() {
print(randNoReplace(2, 9));
}
List<int> randNoReplace(int numToPick, int batchMax) {
List<int> numsPicked = List(numToPick);
List<int> tmpArray = List(batchMax);
//this for loop creates the tmpArray from 0 to batchMax.
for (int i = 0; i <= batchMax; i++) {
tmpArray[i] = i;
}
//this for loop randomly scrambles said tmpArray.
for (int i = 0; i <= batchMax; i++) {
int randIndex = Random().nextInt(batchMax);
int tmp = tmpArray[i];
tmpArray[i] = tmpArray[randIndex];
tmpArray[randIndex] = tmp;
}
//finally, this for loop adds the first numToPick entries of the scrambled tmpArray and adds them to numsPicked.
for (int i = 0; i < numToPick; i++) {
numsPicked[i] = tmpArray[i];
}
return numsPicked;
}
So, for example, with 2 and 9 respectively, this algorithm should theoretically give me 2 random non-duplicate numbers in the range [0, 9].

I think the main issue in your code is that your first two for-loops are going from 0 to
batchMax including batchMax. This is a problem since you are using batchMax to specify the size of your tmpArray. Since the index of a List starts at 0, we cannot ask for the batchMax-element but at most batchMax - 1.
So you code should properly be (or `tmpArray should be one element bigger):
import 'dart:math';
void main() {
print(randNoReplace(2, 9));
}
List<int> randNoReplace(int numToPick, int batchMax) {
List<int> numsPicked = List(numToPick);
List<int> tmpArray = List(batchMax);
//this for loop creates the tmpArray from 0 to batchMax.
for (int i = 0; i < batchMax; i++) {
tmpArray[i] = i;
}
//this for loop randomly scrambles said tmpArray.
for (int i = 0; i < batchMax; i++) {
int randIndex = Random().nextInt(batchMax);
int tmp = tmpArray[i];
tmpArray[i] = tmpArray[randIndex];
tmpArray[randIndex] = tmp;
}
//finally, this for loop adds the first numToPick entries of the scrambled tmpArray and adds them to numsPicked.
for (int i = 0; i < numToPick; i++) {
numsPicked[i] = tmpArray[i];
}
return numsPicked;
}
Some other minor comments:
You should properly not initialize a new Random() object each time you need a random number. Instead, you should create one instance and reuse it.
Your code are not making much use of the Dart SDK. In fact, your code could properly be simplified into:
void main() {
print(randNoReplace(2, 9));
}
List<int> randNoReplace(int numToPick, int batchMax) =>
(List.generate(batchMax, (index) => index)..shuffle())
.sublist(0, numToPick);

Related

Am I crazy for thinking this program is O(n) runtime? My TA says it's O(n^2)

Code below, it should be O(n). There are two loops, I know this. But that doesn't necessarily mean it's O(n^2). The function loops won't run more than n + 1 times (at least as far as I can tell!). That should be O(n). Am I wrong? Can someone help me out? Thanks!
EDIT: The program puts odd integers at the front and even integers at the back of an array!!!
public class Main {
public static void main(String[] args) {
int[] array = new int[]{5, 4, 3, 2, 1, 0};
organizeArray(array);
for (int j = 0; j < array.length; j++) {
System.out.println(array[j]);
}
}
public static void organizeArray(int[] array) {
int end = array.length - 1;
for (int i = 0; i < array.length; i++) {
int temp = 0;
while (true) {
if (i == end)
break;
if (array[i] % 2 == 0) {
temp = array[i];
array[i] = array[end];
array[end] = temp;
end = end - 1;
}
if (array[i] % 2 != 0)
break;
}
if (i == end)
break;
}
}
}
As the other question was a duplicate of this one, let me post my answer here.
The code is O(n) as you either increase i or reduce end. In any case, you decrease the rest of work (n) by one.
For your upcoming homework: You can test your thoughts about big-O easily just by trying out. Most of the time the number of tests doesn't need to be very big. It will not be a proof but it gives you a good hint if your thoughts are correct or not.
Here's is my code for your problem with 100 tests. It produces 100 pairs of numbers: The length of the array and the number of loops. You take this list and bring it to a graph.
public class Main {
public static void main(String[] args) {
Main main = new Main();
Random random = new Random();
for (int i = 0; i < 100; i++) {
int[] array = new int[random.nextInt(10000 - 10) + 10]; // between 10 and 9999 numbers long
for (int j = 0; j < array.length; j++) array[j] = random.nextInt();
main.organize(array);
}
}
private int[] organize(int[] array) {
long loops = 0;
int end = array.length-1;
// I've shorten your code here. This does the same with less breaks
for (int i = 0; i < end; i++) {
while(i < end && array[i] % 2 == 0) {
swap(array, i, end--);
loops++;
}
}
System.out.printf("%d\t%d\n", array.length, loops);
return array;
}
private void swap(int[] array, int a, int b) {
int t = array[a];
array[a] = array[b];
array[b] = t;
}
}
And the graph looks like a straight line. So your proof should result in O(n), right?
Interesting code. The inner for loop will break when the i'th element is odd. If its not odd then it will swap elements from the end until an odd one is found. Since end is decremented upon each swap and the program completes when i reaches end, it follows that i or end can get incremented/decremented, respectively at most O(n) times. Because of this, and because all other operations in the loops are O(1), the program indeed runs in time O(n) despite there being nested loops.

Create Random Number List With No Repetition

I'm looking to create a list of 'random' numbers from 1 to 15 but without any repetition. I have created an array and looking to store each number in it but can't figure out how to do this. I've gotten as far as creating the random list and storing them in the array but can't quite get to ensure there are no repetitions. Any help would be appreciated. My code is as follows:
int[] myList = new int[15];
Random random = new Random();
for (int i = 0; myList.Length; i++)
{
myList[i] = random.Next(1, 15);
}
Because the size of your list is equal to the possible values, you can just create the list in normal order:
int[] myList = new int[15];
for (int i = 0; i < myList.Length; i++)
{
myList[i] = i + 1;
}
and then shuffle it, for example by assigning a random value to each entry and sort by that value:
Random random = new Random();
myList = myList.OrderBy(a => random.Next()).ToArray();
You can do it using Fisher–Yates shuffle.
Sample Implementation:
int n = 15;
int[] myList = new int[n];
Random random = new Random();
for (int i = 0; i < n; i++)
{
myList[i] = i + 1;
}
for (int i = n - 1; i >= 1; i--)
{
int j = random.Next(1, i);
int temp=myList[i];
myList[i]=myList[j];
myList[j]=temp;
}
You need to get the algorithm right.
Start from i=15
Pick a random number from 1 to i.
Append it to the list.
Swap it with (i-1)th index.
Decrement i by 1.
Repeat the above steps.
The code for above can be:
int[] myList = new int[15];
int[] original_list = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
Random random = new Random();
for (int i = myList.Length; i>=0; i--)
{int randNo = random.Next(0, i-1);
myList[i] = original_list[randNo];
swap(original_list[i-1],original_list[randNo]); //your swap method
}

can any body help me with this code of multiplication matrix by matrix ?

this is the code that i write i tried it but it just work for same length matrix and its should work for the two matrix that the columns of the first one as the the rows of the Second ..
void msklret(int matrixA[M][N],int matrixB[M][N],int matrixC[M][N],int r1,intc2,int r2)
{
int i , j,k,sum;
for(i=0; i<r1; i++)
{
for(j=0; j<c2; j++)
{
sum = 0;
for(k=0; k<r2; k++)
{
sum += matrixA[i][k] * matrixB[k][j];
}
matrixC[i][j]=sum;
sum=0;`
}
}
So assuming you are looking for the naive algorithm:
This is written in c#
public float[,] MatrixMultiply(float[,] leftMat, float[,] rightMat)
{
// get the required row and column ranks for both matrices
int leftRowNum = leftMat.GetLength(0);
int rightRowNum = rightMat.GetLength(0);
int leftColNum = leftMat.GetLength(1);
int rightColNum = rightMat.GetLength(1);
// Check that the inner dimensions are the same
if(leftColNum != rightRowNum)
return null;
int innerLen = leftColNum;
// now define resulting matrix dimensions
float[,] result = new float[leftRowNum,rightColNum];
// perform the multiplication using 3 nested for loops
for(int i = 0; i < leftRowNum; i++)
{
for(int j = 0; j < rightColNum; j++)
{
for(int inner = 0; inner < innerLen; inner++)
{
result[i,j]+= leftMat[i,inner]*rightMat[inner,j];
}
}
}
return result;
}
Now your code would be:
void msklret(int matrixA[M][N],int matrixB[M][N],int matrixC[M][N],int r1,intc2,int r2)
float[,] result = MatrixMultiply(MatrixMultiply(matrixA,matrixB),matrixC);
Which can also be written:
float[,] result = MatrixMultiply(matrixA,MatrixMultiply(matrixB,matrixC));
Given the associative property of matrix multiplication.

interviewstreet Triplet challenge

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.

How to calculate the statistical mode in Processing / Arduino

I'm a design teacher trying to help a student with a programming challenge, so I code for fun, but I'm no expert.
She needs to find the mode (most frequent value) in a dataset built using data from sensors coupled to an Arduino, and then activate some functions based on the result.
We've got most of it figured out, except how to calculate the mode in Arduino. I found the post Get the element with the highest occurrence in an array that solves the problem in JavaScript, but I haven't been able to "port" it.
I've used a HashMap to replace the js {} dynamic object instance and floats, but #weberik's port looks more straightforward.
void setup() {
int numValues = 10;
float[] values = new float[numValues]; //Create an empty sample array
for(int i = 0 ; i < numValues ; i++) values[i] = random(0.0,100.0); //Populate it with random values.
println("mode: " + mode(values));
}
float mode(float[] source) {
if (source.length == 0)
return -1;
HashMap<Float,Integer> modeMap = new HashMap<Float,Integer>();
float result = source[0];
int maxCount = 1;
for (int i = 0; i < source.length; i++) {
float el = source[i];
if (modeMap.get(el) == null)
modeMap.put(el,1);
else
modeMap.put(el,modeMap.get(el)+1);
if (modeMap.get(el) > maxCount) {
result = el;
maxCount = modeMap.get(el);
}
}
return result;
}
You've mentioned sensor input, so I presume data will be sampled continuously, so values could be stored at a certain interval, then sent to Processing for the mode.
Just a wild guess, but isn't she looking to average/smooth out sensor readings a bit?
If so, she could cache a few values (say 10) in an array in Arduino and get the average everytime a new values is added:
int vals[10]; //Array to store caches values.
void setup() {
Serial.begin(9600);
for (int i=0 ; i < 10 ; i++)
vals[i] = 0; //Init with zeroes
}
void loop() {
delay(100);
int currentVal = average(analogRead(0));
//Serial.print(currentVal,BYTE);
Serial.println(currentVal);
}
int average(int newVal) {
int total = 0; //Used to store the addition of all currently cached values
for(int i = 9; i > 0; i--) { //Loop backwards from the one before last to 0
vals[i] = vals[i-1]; //Overwrite the prev. value with the current(shift values in array by 1)
total += vals[i]; //Add to total
}
vals[0] = newVal; //Add the newest value at the start of the array
total += vals[0]; //Add that to the total as well
return total *= .1; //Get the average (for 10 elemnts) same as total /= 10, but multiplication is faster than division.
}
I ported the code from your linked post to Processing, but it's limited to int arrays.
I hope that helps.
void setup()
{
int[] numbers = {1, 2, 3, 2, 1, 1, 1, 3, 4, 5, 2};
println(mode(numbers));
}
int mode(int[] array) {
int[] modeMap = new int [array.length];
int maxEl = array[0];
int maxCount = 1;
for (int i = 0; i < array.length; i++) {
int el = array[i];
if (modeMap[el] == 0) {
modeMap[el] = 1;
}
else {
modeMap[el]++;
}
if (modeMap[el] > maxCount) {
maxEl = el;
maxCount = modeMap[el];
}
}
return maxEl;
}

Resources