Programming Forums
User Name Password Register
 

RSS Feed
FORUM INDEX | TODAY'S POSTS | UNANSWERED THREADS | ADVANCED SEARCH

Reply
 
Thread Tools Display Modes
Old Jul 1st, 2008, 1:38 PM   #1
Sane
Programming Guru
 
Sane's Avatar
 
Join Date: Apr 2005
Location: Waterloo, Ontario
Posts: 2,028
Rep Power: 6 Sane will become famous soon enough
Send a message via MSN to Sane
SMAC #2 [06-08] - Identification Cards (Advanced)

The test data for identification cards is too large to be attached, and has been uploaded here: http://www.2shared.com/file/3529149/5177bf74/cards.html


Identification Cards (Advanced)

Despite the difficulty of this problem, I am happy to see that several people attempted the problem.

Even though no one got the "correct" answer, most peoples' logic were very close and only some minor fixes were necessary to get perfect.

Jimbo's solution was the best, with only one change needed to get perfect.


--------------

The input files were carefully engineered to try to exploit every possible mistake.

Here is a description of each input file, to help you understand the cases you did not handle:

1) The Sample Data #1
2) The Sample Data #2
3) A test for being able to use single digit cards.
4) A very sparse graph where you could start with any card to arrange them all in a line.
5) A very sparse graph where two nodes have unbalanced in/out-degrees, but no Eulerian path.
6) A very dense graph with cards that have same start and end digits, and has to start and end on a specific card.
7) A sparse graph that is disconnected (Two lines can be formed). Each line can start on any card within its disjoint graph.
8) A very dense graph that is disconnected (Two lines can be formed). Each line can start on any card within its disjoint graph.
9) A dense graph that can start on any node, but follows a rather complicated path to use every card.
A) A sparse graph which has two obscure verticies with unbalanced in/out-degrees, but no Eulerian path.

Sparse/dense refers to how many different edges there are.
In the spare graphs, the first and last digits were mostly the same.
In the dense graphs, there were many different combinations of first and last digits.

--------------


Now, on to the solution.

Identification Cards is another problem involving graph theory.

The major observation is that the only thing that "matters" about a card is its first and last digit. It does not matter what the other digits are. This reduces the number of different cards from 1,000,000 to 100 (00 to 99); a great start.

In this question, the vertecies and edges of the graph are a little more difficult to identify.

In short: digits are the vertecies, and cards are the edges.

For example, the card "50009" joins the verticies "5" and "9" by a directed edge.

Thus, there are 10 vertecies (0-9) and 100 possible edges (10*10).

We can also label an edge according to how many duplicate edges exist between the two vertecies.

For example, here is some input data, and its corresponding graph:

11
10001
10005
20001
20005
20009
20509
50302
50502
50702
90005
90505




Using every card is now the equivilent of traversing every edge exactly once.

Doing so is known as forming a Eulerian Path.

In this particular graph, the only possible Eulerian path starts at "2" and ends on "5":

2-1-1-5-2-5-2-9-5-2-9-5

20001
10001
10005
50302
20005
50502
20009
90005
50702
20509
90505


The reason you must start at "2", is because the number of edges that point to 2 is one less than the number of edges that leave 2.

Similarly, the reason the path must end at "5", is because the number of edges that point to 5 is one more than the number of edges that leave 5.

Just try to find a path that proves otherwise!


The number of 'pointing' and 'leaving' edges is referred to as a node's "in-degree" and "out-degree", respectively.

As it turns out, in a directed graph, there exists a Eulerian path if and only if the in-degree and out-degree of every node differ by no more than 1 on no more than 2 two nodes.

These two nodes are always the start and end nodes. If every node has the same in-degree and out-degree, the Eulerian path can start on any node (and will always end on that same node).


There are a couple additional things to handle:

Since numerous edges can exist between the same two nodes, you must be careful to make sure the degrees differ by no more than 1. Some people simply counted how many nodes were unbalanced. But there are many cases where a Eulerian path can't be found even if only two nodes are unbalanced.

For example,

12
102
112
122
21
201

1 has four edges to 2, and 2 has two edges to 1. Even though two nodes are unbalanced, no Eulerian path can be found.

The solution is to total the differences in in-degrees and out-degrees, and make sure it's less than or equal to 2.


The other problem is the digraph must be at least "weakly connected" (if the edges are made undirected, every vertex can be reached). The reason is because you can have two disjoint portions of the graph which both contain a Eulerian cycle, yet the total balance will still be 0.

For example,

1002
2001
5006
6005

The total balance is 0, yet no Eulerian path can be found since the graph is disconnected.

The solution is to treat the edges as undirected, and count the number of reachable vertecies with a depth first search. Then make sure it equals the number of vertecies which have been mentioned.


And here it is all together:

C Syntax (Toggle Plain Text)
  1. #include <stdio.h>
  2. #include <string.h>
  3. #define MAX 10
  4. #define ABS(x) ((x)<0?-(x):(x))
  5.  
  6. int vis[MAX] = {0};
  7. int ins[MAX] = {0};
  8. int out[MAX] = {0};
  9. int undir[MAX][MAX] = {0};
  10. char card[15];
  11.  
  12. int count(int i) {
  13. int j, s=0;
  14. if(vis[i]) return 0;
  15. vis[i] = 1;
  16. for(j=0; j<MAX; j++) if(undir[i][j]) s += count(j);
  17. return s+1;
  18. }
  19.  
  20. int iseuler() {
  21. int i, delta=0;
  22. for(i=0; i<MAX; i++) delta += ABS(ins[i] - out[i]);
  23. return delta <= 2;
  24. }
  25.  
  26. int main() {
  27. int i, j, k, n, dig=0;
  28.  
  29. freopen("cards.in", "rt", stdin);
  30. freopen("cards.out", "wt", stdout);
  31.  
  32. scanf("%d", &n);
  33. for(i=0; i<n; i++) {
  34. scanf("%s", card);
  35. j = card[0]-'0';
  36. k = card[strlen(card)-1]-'0';
  37. // Link vertecies with undirected edge
  38. undir[j][k] = undir[k][j] = 1;
  39. // Increment the degrees on each node
  40. out[j]++;
  41. ins[k]++;
  42. // Count existing vertecies
  43. if(!vis[j]) vis[j] = ++dig;
  44. if(!vis[k]) vis[k] = ++dig;
  45. }
  46.  
  47. memset(vis, 0, sizeof(vis));
  48. if(count(j) == dig && iseuler()) printf("Yep!\n");
  49. else printf("Vladimir needs better entertainment.\n");
  50.  
  51. return 0;
  52. }
__________________
Looking for tough programming challenges? Try participating in Sane's Monthly Algorithms Challenges!
Composing Techno is a little side hobby of mine. Techno by DJ Sane. All free for download.
Sane is online now   Reply With Quote
Reply

Bookmarks

Tags
smac advanced solutions

« Previous Thread in Forum | Next Thread in Forum »

Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Forum Jump

Similar Threads
Thread Thread Starter Forum Replies Last Post
SMAC #2 [06-08] - Escalator Troubles (Senior) Sane Software Design and Algorithms 5 Jul 2nd, 2008 12:29 AM
SMAC #1 [05-08] - Results Sane Software Design and Algorithms 6 Jun 2nd, 2008 5:56 PM
advanced user output l2u C++ 6 May 9th, 2007 9:16 PM
dealing cards brad sue C 21 Mar 28th, 2006 2:21 AM
CSS3 Advanced Layout Module titaniumdecoy HTML / XHTML / CSS 1 Dec 25th, 2005 1:06 AM




DaniWeb IT Discussion Community
All times are GMT -5. The time now is 2:23 PM.

Powered by vBulletin® Version 3.7.0, Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.
Copyright ©2007 DaniWeb® LLC