I'm currently making a quiz app. When a user starts the quiz random questions show up like you would expect from a quiz app. The problem is, it is not quite random. It does show random questions, but the questions repeat. I wanted to make sure they do not repeat until the end! My code is :
int Questions = arc4random_uniform(142);
switch (Questions) {
case 0:
break;
case 1:
break;
(...)
Isn't there a better way to do it? A way to just not repeat the questions? Thank you so much!
A shuffle may be your best solution:
// Setup
int questionCount = 10; // real number of questions
NSMutableArray *questionIndices = [NSMutableArray array];
for (int i = 0; i < questionCount; i++) {
[questionIndices addObject:#(i)];
}
// shuffle
for (int i = questionCount - 1; i > 0; --i) {
[questionIndices exchangeObjectAtIndex: i
withObjectAtIndex: arc4random_uniform((uint32_t)i + 1)];
}
// Simulate asking all questions
for (int i = 0; i < questionCount; i++) {
NSLog(#"questionIndex: %i", [questionIndices[i] intValue]);
}
NSLog output:
questionIndex: 6
questionIndex: 2
questionIndex: 4
questionIndex: 8
questionIndex: 3
questionIndex: 0
questionIndex: 1
questionIndex: 9
questionIndex: 7
questionIndex: 5
ADDENDUM
Example with actual text being printed after shuffling
// Setup
NSMutableArray *question = [NSMutableArray arrayWithObjects:
#"Q0 text", #"Q1 text", #"Q2 text", #"Q3 text", #"Q4 text",
#"Q5 text", #"Q6 text", #"Q7 text", #"Q8 text", #"Q9 text", nil];
// shuffle
for (int i = (int)[question count] - 1; i > 0; --i) {
[question exchangeObjectAtIndex: i
withObjectAtIndex: arc4random_uniform((uint32_t)i + 1)];
}
// Simulate asking all questions
for (int i = 0; i < [question count]; i++) {
printf("%s\n", [question[i] UTF8String]);
}
Sample output:
Q9 text
Q5 text
Q6 text
Q4 text
Q1 text
Q8 text
Q3 text
Q0 text
Q7 text
Q2 text
The idea is to use each question once until all questions have been used.
Sample code. Note that the questionIndex does not repeat.
// Setup
int questionCount = 10; // real number of questions
NSMutableArray *questionIndexes = [NSMutableArray array];
for (int i=0; i<questionCount; i++)
[questionIndexes addObject:#(i)];
// Simulate asking all questions
while (questionIndexes.count) {
// For each round
unsigned long arrayIndex = arc4random_uniform((uint32_t)questionIndexes.count);
int questionIndex = [questionIndexes[arrayIndex] intValue];
[questionIndexes removeObjectAtIndex:arrayIndex];
NSLog(#"arrayIndex: %lu, questionIndex: %i", arrayIndex, questionIndex);
}
NSLog output:
arrayIndex: 9, questionIndex: 9
arrayIndex: 5, questionIndex: 5
arrayIndex: 5, questionIndex: 6
arrayIndex: 3, questionIndex: 3
arrayIndex: 3, questionIndex: 4
arrayIndex: 4, questionIndex: 8
arrayIndex: 2, questionIndex: 2
arrayIndex: 0, questionIndex: 0
arrayIndex: 1, questionIndex: 7
arrayIndex: 0, questionIndex: 1
Any random generator is actually pseudorandom. By default it is started from the same initial value. To make it it "real random" you should supply unique start value i.e. "salt" for each run. As a simplest approach you can use [NSDate timeIntervalSinceReferenceDate].
Put your questions in an array and put the random number in the objectWithIndex method of NSMutableArray. Then remove the question from the array. Whenever a index is chosen, but there is not a question anymore, try it again.
Related
I need an array where I can store 3 values, and calculate the average of it.
After 3s the array is full, I would like to refresh every value starting from begin [0] of the array. So every 3s the the array is updated and I have the most recent average. For the moment when I add an object the array keeps growing.
This is the code I have at the moment:
//Inside function which loops every second so I can access myValue
self.myArray = [[NSMutableArray alloc] initWithCapacity:3];
[self.myArray addObject:[NSNumber numberWithDouble:myValue]];
for(int i = 0; i < self.myArray.count; i++) {
NSLog(#"Array %d: %#", i, self.myArray[i]);
}
Output
Array 0: 2
Array 1: 4
Array 2: 5
Array 3: 6
Array 4: 1
Just check if the size of your array is larger than 3. If so, remove the oldest element.
Here is a possible implementation:
Alloc and init the array:
self.myArray = [[NSMutableArray alloc] init];
Insert a new object and delete the oldest one:
[self.myArray insertObject:object atIndex:0];
if ( self.myArray.count > 3 )
{
[self.myArray removeLastObject];
}
It looks like you're trying to calculate a running average that gets updated every second. Here's a simple alternative approach that may work for you.
Initialize the average:
runningAverage = myValue;
Inside the loop:
const int WEIGHT = 3;
runningAverage = (runningAverage * (WEIGHT - 1) + myValue) / WEIGHT;
Here's what the output would look like:
Input: 1, 2, 3, 4, 101, 6, 7, 8
(Using an array)
Output: -, -, 2, 3, 36, 37, 38, 7
(Using running average)
Output: 1, 1.33, 1.88, 2.59, 35.4, 25.6, 19.4, 15.6
I have an array of an array of objects. The inner arrays have been sorted in order then added to an overall array. All the inner objects are the same thing with different values.
I am trying to go through those arrays and organize the objects in order from the average index value.
Example of the inner arrays sorted
obj 1 | obj 2 | obj 2
obj 2 | obj 1 | obj 1
obj 3 | obj 3 | obj 4
obj 4 | obj 4 | obj 3
then the output i would need from that after getting the average would be
obj 2
obj 1
obj 3
obj 4
I really only need the top three index averages but I would like to get all of them. So for example to get 3 I could do this
for (NSArray* innerArray in outterArray) {
for (NSString* str in innerArray) {
if ([innerArray indexOfObject:str] == 0) {
[first addObject:str];
}else if([innerArray indexOfObject:str] == 1){
[second addObject:str];
}else if ([innerArray indexOfObject:str] == 2){
[third addObject:str];
}
}
}
Then go through those three arrays and see what pops up where but there must be a better way of doing this and its probably something simple but I cant see it
All objects occur the same number of times, therefore you can compute the sum
of indices instead of the average for each object.
This can be done by enumerating once over all inner dictionaries, and updating
a hash map (dictionary) with the sum of indices for the current object.
(Note that indexOfObject:
is not needed here to locate the objects in the inner array.)
Then sort the objects according to the sum of the indices (which is the value
of the object in the dictionary):
NSArray *outerArray = #[
#[#"obj 1", #"obj 2", #"obj 3", #"obj 4"],
#[#"obj 2", #"obj 1", #"obj 3", #"obj 4"],
#[#"obj 2", #"obj 1", #"obj 4", #"obj 3"],
];
NSMutableDictionary *map = [NSMutableDictionary dictionary];
for (NSArray *innerArray in outerArray) {
NSUInteger index = 0; // Index of next object in the inner array
for (NSString *str in innerArray) {
// Add current index of this object to previous sum and update hash map
NSUInteger tmp = index + [map[str] unsignedIntegerValue];
map[str] = #(tmp);
index++;
}
}
NSArray *sorted = [[map allKeys] sortedArrayUsingComparator:^NSComparisonResult(NSString *obj1, NSString *obj2) {
return [map[obj1] compare:map[obj2]];
}];
NSLog(#"%#", sorted);
Output:
(
"obj 2",
"obj 1",
"obj 3",
"obj 4"
)
The dictionary map in this case is
{
"obj 1" = 2; // "obj 1" at indices 0 + 1 + 1
"obj 2" = 1; // "obj 2" at indices 1 + 0 + 0
"obj 3" = 7; // "obj 3" at indices 2 + 2 + 3
"obj 4" = 8; // "obj 4" at indices 3 + 3 + 2
}
I have a dynamic array. I need to display tableview as following scenario...
In the First cell i need to display 1 item.
In the second cell i need to display 2 items.
In the third cell i need to display 3 items.
In the forth cell i need to display 1 item.
In the fifth cell i need to display 2 items.
In the sixth cell i need to display 3 items.
and so on...
Could any one please suggest how to return no of rows in a section.
Try this :
int noOfRow = total/2 + ceil((total % 3)/3.0);
Simple logic for this is:
NoOfRows = TotalCount / 2
For e.g.:
If last value is 6 then, total no of rows are (6 / 2) = 3
If last value is 12 then, total no of rows are (12 / 2) = 6
You have to think logical that's it.
Hope this helps.
A faster method might be:
Notice in the divide by 2 method, most numbers work. The ones don't work are:
2, 4, 8, 10... basically, even numbers that aren't divisible by 6.
So we can come up with something like:
int count = array.count;
if (count % 2 == 0 && count % 6 != 0) {
count + 2;
}
int rows = ceilf(count / 2);
Or we can write a for loop:
int counter = array.size;
int rows = 0;
int dec = 1;
while (counter > 0) {
rows++;
counter - dec;
dec = dec % 3 + 1;
}
The for loop is of course, slower.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
i am working to find the solution steps for a randomly generated "15 puzzle". So tell me which is the best algorithm to use to solve it fast. Provide me approach to do so.
I am making a tree of nodes containing 4*4 array and traversing through all the node which are not yet processed and when i get the solution i stop the iteration.
In viewcontroller i have some code as
- (IBAction)getSolution:(id)sender {
while (!appDelegate.isResultFound) {
TreeNode *node=[self nodeWithLowestCostAndUnproceessedInRootNode];
[node expandNodeToChilds];
//break;
}
NSLog(#"Result Found");
if([appDelegate.result isEqualToString:#""])
NSLog(#"No move required");
else
NSLog(#"%#",appDelegate.result);
}
-(TreeNode*)nodeWithLowestCostAndUnproceessedInRootNode{
TreeNode *node1;
int lowestCost=200;
for (TreeNode *node in appDelegate.treeNodes) {
if([node myHeuristicsFunction]<lowestCost&&node.isProcessed==NO){
node1=node;
lowestCost=[node.cost intValue];
}
}
return node1;}
and in node class i am expanding the node as (except the move used by the parent)
-(void)expandNodeToChilds{
[self checkMovesForEmptyPlace];
if(top.x>=0){
[self addPuzzleBoxToTreeBySwapingPoint:top withMove:#"Bottom"];
}
if(right.y<=3){
[self addPuzzleBoxToTreeBySwapingPoint:right withMove:#"Left"];
}
if(bottom.x<=3){
[self addPuzzleBoxToTreeBySwapingPoint:bottom withMove:#"Top"];
}
if(left.y>=0){
[self addPuzzleBoxToTreeBySwapingPoint:left withMove:#"Right"];
}
self.isProcessed=true;}
Currently i am using manhattan distance with A*, but not getting the result in significant time, app memory increases to 1GB and app crashes.
I am assuming that you are looking for the shortest way to reach the goal for this puzzle. You can use A* algorithm with the manhattan distance between the current board and the goal board as the cost function.
The following code in Java implements the algorithm. The function Solver takes as input N, the size of the NxN board and then the corresponding N*N numbers ranging from [0,N^2] giving the locations of the numbers in the 2d grid. It outputs the minimum number of moves that are required and the actual moves. 0 indicates the empty position in the puzzle.
import java.io.InputStreamReader;
import java.util.*;
class Solver{
private int N ;
private int minMoves ;
public static int[] correctRow;
public static int[] correctCol;
private class Node implements Comparable<Node>{
private Board board ;
private int moves ;
private Node prevNode ;
public Node(Board board,int moves,Node prev){
this.board = board ;
this.moves = moves ;
this.prevNode = prev ;
}
public int compareTo(Node that){
int thisPriority = this.moves+this.board.manhattan() ;
int thatPriority = that.moves+that.board.manhattan() ;
if(thisPriority<thatPriority){
return -1 ;
}else if(thisPriority>thatPriority){
return 1 ;
}else{
return 0 ;
}
}
}
private Node lastNode ;
private boolean solvable ;
public Solver(Board initial){
N = initial.dimension() ;
PriorityQueue<Node> pq = new PriorityQueue<Node>() ;
PriorityQueue<Node> pq2 = new PriorityQueue<Node>() ;
pq.add(new Node(initial,0,null)) ;
pq2.add(new Node(initial.twin(),0,null)) ;
while(true){
Node removed = pq.poll();
Node removed2 = pq2.poll();
if(removed.board.isGoal()){
minMoves = removed.moves ;
lastNode = removed ;
solvable = true ;
break ;
}
if(removed2.board.isGoal()){
minMoves = -1 ;
solvable = false ;
break ;
}
Iterable<Board> neighbors = removed.board.neighbors() ;
Iterable<Board> neighbors2 = removed2.board.neighbors() ;
for(Board board : neighbors){
if(removed.prevNode != null && removed.prevNode.board.equals(board) ){
continue ;
}
pq.add(new Node(board,removed.moves+1,removed)) ;
}
for(Board board : neighbors2){
if(removed2.prevNode != null && removed2.prevNode.board.equals(board) ){
continue ;
}
pq2.add(new Node(board,removed2.moves+1,removed2)) ;
}
}
}
public boolean isSolvable(){
return solvable ;
}
public int moves(){
return minMoves ;
}
public Iterable<Board> solution(){
if(!isSolvable()){
return null ;
}
Stack<Board> stack = new Stack<Board>() ;
Node node = lastNode ;
while(true){
if(node == null) break ;
Board board = node.board ;
node = node.prevNode ;
stack.push(board) ;
}
return stack ;
}
static void initCorrectRowsCols(int N){
correctRow = new int[N*N] ;
int z = 0 ;
for(int i = 0 ; i < N ; i++ ){
for(int j = 0 ; j < N ; j++ ){
correctRow[z++] = i ;
}
}
z = 0 ;
correctCol = new int[N*N] ;
for(int i = 0 ; i < N ; i++ ){
for(int j = 0 ; j < N ; j++ ){
correctCol[z++] = j ;
}
}
}
public static void main(String[] args) {
long start = System.currentTimeMillis();
// create initial board from file
Scanner in = new Scanner(new InputStreamReader(System.in));
int N = in.nextInt();
initCorrectRowsCols(N);
int[][] blocks = new int[N][N];
for (int i = 0; i < N; i++)
for (int j = 0; j < N; j++)
blocks[i][j] = in.nextInt();
Board initial = new Board(blocks);
// solve the puzzle
Solver solver = new Solver(initial);
long end = System.currentTimeMillis();
System.out.println("time taken " + (end-start) + " milli seconds");
// print solution to standard output
if (!solver.isSolvable())
System.out.println("No solution possible");
else {
System.out.println("Minimum number of moves = " + solver.moves());
Stack<Board> stack = new Stack<Board>();
for (Board board : solver.solution())
stack.push(board);
while(!stack.isEmpty()){
System.out.println(stack.pop());
}
}
}
}
class Board{
private int[][] array ;
private int N ;
int emptyRow;
int emptyCol;
boolean reached;
int manhattan = 0;
public Board(int[][] blocks){
N = blocks.length ;
array = new int[N][N] ;
reached = true;
for(int i = 0 ; i < N ; i++ ){
for(int j = 0 ; j < N ; j++ ) {
array[i][j] = blocks[i][j] ;
if(array[i][j] == 0){
emptyRow = i;
emptyCol = j;
}
if(array[i][j] != N*i + j+1){
if(!(i==N-1 && j==N-1)){
reached = false;
}
}
int num = array[i][j] ;
if(num==0){
continue ;
}
int indManhattan = Math.abs(Solver.correctRow[num-1] - i)
+ Math.abs(Solver.correctCol[num-1]-j) ;
manhattan += indManhattan ;
}
}
}
public int dimension(){
return N ;
}
public int hamming(){
int outOfPlace = 0 ;
for(int i = 0 ; i < N ; i++ ) {
for(int j = 0 ; j < N ; j++ ){
if(i==N-1 && j==N-1) {
break ;
}
if(array[i][j] != i*N+j+1){
outOfPlace++ ;
}
}
}
return outOfPlace ;
}
public int manhattan(){
return manhattan ;
}
public boolean isGoal(){
return reached ;
}
public Board twin(){
int[][] newArray = new int[N][N] ;
for(int i = 0 ; i < N ; i++ ){
for(int j = 0 ; j < N ; j++ ){
newArray[i][j] = array[i][j] ;
}
}
for(int i = 0 ; i < 2 ; i++ ) {
if(newArray[i][0]==0 || newArray[i][5]==0){
continue ;
}
int temp = newArray[i][0] ;
newArray[i][0] = newArray[i][6] ;
newArray[i][7] = temp ;
break ;
}
return new Board(newArray) ;
}
public boolean equals(Object y){
if(y==this){
return true ;
}
if(y == null){
return false ;
}
if(y.getClass() != this.getClass()){
return false ;
}
Board that = (Board)y ;
if(that.array.length != this.array.length){
return false ;
}
for(int i = 0 ; i < N ; i++ ) {
for(int j = 0 ; j < N ; j++ ) {
if(that.array[i][j] != this.array[i][j] ){
return false ;
}
}
}
return true ;
}
public Iterable<Board> neighbors(){
Queue<Board> q = new ArrayDeque<Board>() ;
int firstIndex0 = 0 ;
int secondIndex0 = 0 ;
for(int i = 0 ; i < N ; i++ ){
for(int j = 0 ; j < N ; j++ ) {
if(array[i][j] == 0){
firstIndex0 = i ;
secondIndex0 = j ;
break ;
}
}
}
if(secondIndex0-1>-1){
int[][] newArr = getCopy() ;
exch(newArr,firstIndex0,secondIndex0,firstIndex0,secondIndex0-1) ;
q.add(new Board(newArr)) ;
}
if(secondIndex0+1<N){
int[][] newArr = getCopy() ;
exch(newArr,firstIndex0,secondIndex0,firstIndex0,secondIndex0+1) ;
q.add(new Board(newArr)) ;
}
if(firstIndex0-1>-1){
int[][] newArr = getCopy() ;
exch(newArr,firstIndex0,secondIndex0,firstIndex0-1,secondIndex0) ;
q.add(new Board(newArr)) ;
}
if(firstIndex0+1<N){
int[][] newArr = getCopy() ;
exch(newArr,firstIndex0,secondIndex0,firstIndex0+1,secondIndex0) ;
q.add(new Board(newArr)) ;
}
return q ;
}
private int[][] getCopy(){
int[][] copy = new int[N][N] ;
for(int i = 0 ; i < N ; i++ ) {
for(int j = 0 ; j < N ; j++ ){
copy[i][j] = array[i][j] ;
}
}
return copy ;
}
private void exch(int[][] arr, int firstIndex,int secIndex,int firstIndex2,int secIndex2){
int temp = arr[firstIndex][secIndex] ;
arr[firstIndex][secIndex] = arr[firstIndex2][secIndex2] ;
arr[firstIndex2][secIndex2] = temp ;
}
public String toString(){
StringBuilder s = new StringBuilder() ;
s.append(N + "\n") ;
for(int i = 0 ; i < N ; i++ ){
for(int j = 0 ; j < N ; j++ ) {
s.append(String.format("%4d",array[i][j])) ;
}
s.append("\n") ;
}
return s.toString() ;
}
}
So for the input
3
7 8 5
4 0 2
3 6 1
The algorithm generates the output
Minimum number of moves = 28
3
7 8 5
4 0 2
3 6 1
3
7 0 5
4 8 2
3 6 1
3
7 5 0
4 8 2
3 6 1
3
7 5 2
4 8 0
3 6 1
3
7 5 2
4 0 8
3 6 1
3
7 5 2
4 6 8
3 0 1
3
7 5 2
4 6 8
3 1 0
3
7 5 2
4 6 0
3 1 8
3
7 5 2
4 0 6
3 1 8
3
7 5 2
0 4 6
3 1 8
3
0 5 2
7 4 6
3 1 8
3
5 0 2
7 4 6
3 1 8
3
5 4 2
7 0 6
3 1 8
3
5 4 2
7 1 6
3 0 8
3
5 4 2
7 1 6
0 3 8
3
5 4 2
0 1 6
7 3 8
3
5 4 2
1 0 6
7 3 8
3
5 0 2
1 4 6
7 3 8
3
0 5 2
1 4 6
7 3 8
3
1 5 2
0 4 6
7 3 8
3
1 5 2
4 0 6
7 3 8
3
1 5 2
4 3 6
7 0 8
3
1 5 2
4 3 6
7 8 0
3
1 5 2
4 3 0
7 8 6
3
1 5 2
4 0 3
7 8 6
3
1 0 2
4 5 3
7 8 6
3
1 2 0
4 5 3
7 8 6
3
1 2 3
4 5 0
7 8 6
3
1 2 3
4 5 6
7 8 0
I would also like to mention that
Finding a shortest solution to an N-by-N slider puzzle is NP-Hard, so it's unlikely that an efficient solution exists.
If you are not looking for a shortest path solution but any solution that runs fast in the input then this paper describes an algorithm that guarantees to perform at most N^3 moves.
Thus although the solution I have given runs fast on most of the inputs, it may fail on other difficult inputs.
Also note that not all puzzles are solvable. For the puzzles that cannot be solved, the algorithm prints that the puzzle cannot be solved.
PS. The algorithm implemented above follows the guidelines of this programming assignment.
Let's say I have an NSArray of 60 elements. Out of it, I would like to get 4 values at the indexes 15, 30, 45, 60. I was trying to put it into a for loop but it didn't work quite well here:
for (int elementIndex = x_valuesDataArray.count / 4; elementIndex < x_valuesDataArray.count; elementIndex = elementIndex + elementIndex){
NSLog(#"Element index is %d", elementIndex);
NSLog(#"Total values %u", x_valuesDataArray.count);
NSString *firstValue = [x_valuesDataArray objectAtIndex:elementIndex];
[xAxisArray02 addObject:firstValue];
}
But my NSLog output says I'm, doing something wrong:
2013-04-12 13:48:59.267 myApp[44682:907] Element index is 15
2013-04-12 13:48:59.269 myApp[44682:907] Total values 60
2013-04-12 13:48:59.270 myApp[44682:907] Element index is 30
2013-04-12 13:48:59.271 myApp[44682:907] Total values 60
What am I doing wrong here?
for (int i = 1; i <= 4; i++) {
int elementIndex = x_valuesDataArray.count * i / 4 - 1;
// ...
}
should work. Note that an array with 40 elements has indices 0 .. 39. In this case the above
loop gives the indices 9, 19, 29, 39. It is also assumed that the array has at least 4 elements.
A. The x_valuesDataArray has 60 not 40 elements as you predicted.
B. This line: elementIndex = elementIndex + elementIndex should be
elementIndex = elementIndex + 10
If the valuesDataArray was 40.