C - order of movement in a 2D array for maximum sum collected - c

I've been having trouble with a problem, something like this:
I have a 2D array where each position is filled with a certain number samples (represented by ints). There are nanorobots, each going in a straight line through a part of a line of column (each with a pre-specified way), collecting all samples along the way. If a nanorobot collects samples on a position, the position becomes contaminated and if another robot comes there, it gets confused and stops. I can deploy the robots in any order, and each robot starts working only after the previous one has stopped.
With this information, I want to find the order in which the highest number of samples is collected.
Any help with the problem would be appreciated, as I am pretty stumped. I have a general idea of how it's done, but can't seem to move forward. One thing specifically is how do I mark which places a robot has been to so that i know where other robots should stop if they come there, every solution I've come up with seems really slow. Thanks.

To help you developing your algorithms, I provide you with a possible data structure:
typedef struct LIST {
int sample;
struct LIST *next;
} t_list;
typedef struct ITEM {
t_list *samples;
int visited;
} t_item;
t_item items[10][10];
This defines an array of 10x10 items. Each item has a list of samples and an indicator that it has been visited ("contaminated"). A list element (a sample) has the sample value and a pointer to the next list element (the next sample). I hope this helps.

Related

what is the conventional way to represent snake when coding snake game in C?

A bit of context:
I have some experience with other programing languages, but when it comes to C my knowledge is not that big. I'm also attempting to make the snake game without relying on dynamic memory allocation which is not the part of std, as it is intended to run on a microcontroller.
I previously coded snake game in python, rust, and java and my go to approach was to store pairs of x and y coordinates in some form of dynamic list or vector. Every iteration of the game loop I would append the element to the list/vector of pairs based on the current last element and and respective dx and dy, and if the snake was not growing deleted or poped the first element of the vector/list, making the snake "move".
I was particularly fond of this approach, since it meant I'm not required to store my entire game field in a 2d array. It also was a very clean implementation in my opinion. Now in C, I have to major problems - no dynamically sized lists and ability to delete first element of the array and shifting all the elements back without iterating through all of the array.
For the first problem, I've considered either using a fixed size array with some limit which would be above reasonable snake length while keeping track of snake length separately, or using a linked list of structs which would contain a nullable pointer to itself. Latter one seems to be unnecessarily complex, while the first one seems like a very dirty fix.
For the second problem, I've considered overriding array pointer with the pointer to its second element, but while that semi worked - I'm concerned with following issues:
do I have to free the previous array pointer (a.k.a. the previous first element)
when doing something like this, I assume that the pointer to the array would keep on growing, and sooner or later it would segfault as it does not reuse the memory it already slided away from.
So I thought I should ask more experienced coders on a cleaner and more conventional ways to implement snake in C.
Thank you in advance,
There is an upper bound on the length of the snake -- the size of your 2d board. And this upper bound is very well achievable if your player is good at the game. Therefore you can preallocate an array of that size and use it as a pool for your linked-list nodes or a circular queue.
You can simplify further by using a 2d array for your board, and storing just the next/previous links within each cell where there's a snake. Then you don't need to store the x/y of each segment:
enum { TYPE_EMPTY, TYPE_FOOD, TYPE_SNAKE };
struct Cell { int type, next, prev; };
struct Cell board[width*height];
int head, tail;
This approach is easy to generalize to multiple players on the same board, multiple items or item types, etc.
There is nothing 'wrong' in storing an explicit 2d representation of your board. In fact it is a natural way to attack the problem. It allows fast checks for self-collisions, among other things. I bet your previous implementations resorted to a slow O(n) check to see if the snake self-intersects, which isn't pretty by itself.

Array Based Implementation of a Vector

Homework Assistance
Describe an array based implementation of a vector such that inserting and
removing at beginning and end of the vector can be done in constant time. Argue
convincingly.
Obviously this is impossible with a straight-up array. If you remove from the front, there will be a hole that needs to be filled in order to maintain the vector property. Of course, if we grab the next element over, we will need to do this n times, so the runtime will be linear, not constant.
Another way would be to grab the last element and stick it in the front, but what good is a data structure that scrambles your data?
What I have done so far is to create an array. The odd number indices are behind some point in the array (preferably the middle for size purposes, but it can be anywhere), then the even number indices are before that point. That takes up a whole bunch of memory and has lots of open slots if that special point is not the centre point. Worst case being 2n. However, it acts like there are no holes because it will always fill the next element out.
Insertion:
private int front = 0;
private int back = 0;
public void insertAtFront(int element)
{
(front+1));
dataArray[2*(front + 1) + 1] = element;
front++;
}
public void insertAtBack(int element)
{
dataArray[2*(back+1)] = element;
back++;
}
For removal, just decrement the front or the back. Then when accessing the array, only allow the values between front and back to be shown.
First, does this meet the requirements of a vector? Second, when removing, I am having some major issues figuring out how to get past that special centre point. Say you want to remove the entire array from the front, when you added everything from the back.
Thank you for any assistance.
The secret is to use two arrays. The end of the first array is the "front". The end of the second array is the "back".
I don't understand what you're trying to do with even and odd indices. But having a start index and an end index is basically the way to go - leave space empty at the front so that you can add elements there, and increment the start index again if you remove an element.
Another option is to use a circular array to allow you to add/remove both at the front and at the end efficiently.
There are other variations that could be applied: can you also find an implementation such that inserting/removing at the start, the end and (exactly) in the middle is efficient and has O(1) time?

"Robot Arm moving block stacks" Programming Challenge in C

I'm trying to resolve this for fun but I'm having a little bit of trouble on the implementation, the problem goes like this:
Having n stacks of blocks containing m blocks each, design a program in c that controlls a robotic arm that moves the blocks form an inicial configuration to a final one using the minimum amount of movements posible, your arm can only move one block at a time and can only take the block at the top of the stack, your solution should use either pointers or recursive methods
In other words the blocks should go from this(suposing there are 3 stacks and 3 blocks):
| || || |
|3|| || |
|2||1|| |
to this:
| ||1|| |
| ||2|| |
| ||3|| |
using the shortest amount of movements printing each move
I was thinking that maybe I could use a tree of some sorts to solve it (n-ary tree maybe?) since that is the perfect use of pointers and recursive methods but so far it has proved unsuccesfull, I'm having lots of trouble defining the estructure that will store all the movements since I would have to check every time I want to add a new move to the tree if that move has not been done before, I want each leaf to be unique so when I find the solution it will give me the shortest path.
This is the data structure I was thinking of:
typedef struct tree(
char[MAX_BLOCK][MAX_COL] value;
struct tree *kids
struct tree *brothers;
)Tree;
(I'm really new at C so sorry beforehand if this is all wrong, I'm more used to Java)
How would you guys do it? Do you have any good ideas?
You have the basic idea - though I am not sure why you have elected to choose brothers over the parent.
You can do this problem with a simple BFS search, but it is a slightly less interesting solution, and not the one you for which seemed to have set yourself up.
I think it will help if we concisely and clearly state our approach to the problem as a formulation of either Dijkstra's, A*, or some other search algorithm.
If you are unfamiliar with Dijkstra's, it is imperative that you read up on the algorithm before attempting any further. It is one of the foundational works in shortest path exploration.
With a familiarity of Dijkstra's, A* can readily be described as
Dijsktra's minimizes distance from the start. A* adds a heuristic which minimizes the (expected) distance to the end.
With this algorithm in mind, lets state the specific inputs to an A* search algorithm.
Given a start configuration S-start, and an ending configuration S-end, can we find the shortest path from S-start to S-end given a set of rules R governed by a reward function T
Now, we can envision our data structure not as a tree, but as a graph. Nodes will be board states, and we can transition from state to state using our rules, R. We will pick which edge to follow using the reward function T, the heuristic to A*.
What is missing from your data-structure is the cost. At each node, you will want to store the current shortest path, and whether it is finalized.
Let's make a modification to your data-structure which will allow us to readily traverse a graph and store the shortest path information.
typedef struct node {
char** boardState;
struct node *children;
struct node *parent;
int distance;
char status; //pseudo boolean
} node;
You may want to stop here if you were interested in discovering the algorithm for yourself.
We now consider the rules of our system: one block at a time, from the top of a stack. Each move will constitue an edge in our graph, whose weight is governed by the shortest number of moves from S-begin plus our added heuristic.
We can then sketch a draft of the algorithm as follows:
node * curr = S-begin;
while (curr != S-end) {
curr->status == 'T'; //T for True
for(Node child : children) {
// Only do this update if it is cheaper than the
int updated = setMin(child->distance, curr->distance + 1 + heuristic(child->board));
if(updated == 1) child->parent = curr;
}
//set curr to the node with global minimum distance who has not been explored
}
You can then find the shortest path by tracing the parents backwards from S-end to S-begin.
If you are interested in these types of problems, you should consider taking a uppergraduate level AI course, where they approach these types of problems :-)

Why exactly do we need a "Circular Linked List" (singly or doubly) data structure?

Why exactly do we need a "Circular Linked List" (singly or doubly) data structure?
What problem does it solve that is evident with simple Linked Lists (singly or doubly)?
A simple example is keeping track of whose turn it is in a multi-player board game. Put all the players in a circular linked list. After a player takes his turn, advance to the next player in the list. This will cause the program to cycle indefinitely among the players.
To traverse a circular linked list, store a pointer to the first element you see. When you see that element again, you have traversed the entire list.
void traverse(CircularList *c) {
if (is_empty(c)) {
return;
}
CircularList start = c;
do {
operateOnNode(c);
c = c->next;
} while(c != start);
}
Two reasons to use them:
1) Some problem domains are inherently circular.
For example, the squares on a Monopoly board can be represented in a circularly linked list, to map to their inherent structure.
2) Some solutions can be mapped to a circularly linked list for efficiency.
For example, a jitter buffer is a type of buffer that takes numbered packets from a network and places them in order, so that (for example) a video or audio player can play them in order. Packets that are too slow (laggy) are discarded.
This can be represented in a circular buffer, without needing to constantly allocate and deallocate memory, as slots can be re-used once they have been played.
It could be implemented with a linked-list, but there would be constant additions and deletions to the list, rather than replacement to the constants (which are cheaper).
Something i found from google.
A singly linked circular list is a linked list where the last node in thelist points to the first node in the list. A circular list does not contain NULL pointers.
A good example of an application where circular linked list should be used is a timesharing problem solved by the operating system.
In a timesharing environment, the operating system must maintain a list of present users and must alternately allow each user to use a small slice of CPU time, one user at a time. The operating system will pick a user, let him/her use a small amount of CPU time and then move on to the next user, etc.
For this application, there should be no NULL pointers unless there is absolutely no one requesting CPU time.
Applications
1) We can use circular linked list any application where the entries appear in a rotating manner.
2) Circular linked list is the basic idea of round robin scheduling algorithm.
A circular linked list can be effectively used to create a queue (FIFO) or a deque (efficient insert and remove from front and back). See http://en.wikipedia.org/wiki/Linked_list#Circularly-linked_vs._linearly-linked
Circular linked lists are widely used in applications where tasks are to be repeated or in time sharing applications. Circular queue can keep a track of tasks which have been performed and which has to be performed,once the specific task is done it jumps to next one and when whole set of task is conpleted it again jumps to first task to complete the remaining job.
In practical use : when you open multiple applications on your system the memory of those applications are saved in a circular fashion, you can observe this if u continuously press win+tab/alt+tab for switching applications.
Also in multiplayer board games ,each player are assigned to node in the linked list and the rotation is performed
Circular linked lists (singly or doubly) are useful for applications that need to visit each node equally and the lists could grow. If the size of the list if fixed, it is much more efficient (speed and memory) to use circular queue.
A circular list is simpler than a normal doubly-linked list. Append is just prepend and shift forward once, Pop back is just shift back once and pop front. By tying the two ends together, you get a double-ended list for the cost of just implementing the operations of a one-ended list.
We can use circularly linked list in resource pooling. If many users want to use a shared resource, we can allocate that resource using circularly linked list.
A good example of an application where circular linked list should be used is a timesharing problem solved by the operating system.

please can some one help me explain linked list?

I have tried a lot to learn linked list.But all my efforts were wasted.Please can some one help me understand linked list by providing his/her own code?Thanks in advance.
A linked list is simply a list of elements (usually called nodes) where each node has a reference (or pointers, in C) to the next node:
http://img837.imageshack.us/img837/5613/ll1s.png
You keep track of the list by having a pointer to the first node (the "head"), and by having the last node point to null
Linked lists where each element points to both the next and previous nodes are called doubly-linked lists.
By following these references, you can traverse the list and get any node.
A common advantage of linked lists over arrays is that you can insert and remove the elements in O(1) (constant) time. The disadvantage is that you have O(N) random-access.
See Wikipedia for more.
Have you play some of these rally games? The organizer left this hints all around the city and you must get one hint and then solve the riddle for getting the position of the next hint. Now, imagine every hint comes with a little prize.
Well, linked list are like that: every element has "content" on it AND the memory address (the hint) for getting the next item. The next item, of course, has another prize and another hint.
A linked list is a series of object each pointing to the next one in the list. The last element in the list has NULL as it's next pointer.
You keep track of the head of the list in your program so you can traverse the list from the start.
You might want to keep track of the current position in the list, but that will depend on your application.
A doubly linked list has a previous element pointer too enabling you to traverse the list in both directions.
This:
typedef struct tagProp
{
rtPropertyKey key;
rtProperty property;
struct tagProp *next;
} TProperty;
defines a property key/value lookup list.
A linked list is implemented as a list of "nodes". The nodes are linked together using pointers. The following code describes one node. The pointer to the next node is called next. In my example, each node contains an integer value as its data.
struct node {
int val;
struct node * next;
};
The fun is how to actually create a list. You have to use malloc to create new nodes. When you malloc the new node, you have to tie into the list using the next pointer.
We can help you more if you specifically tell us what your issues are...

Resources