फैमिली ट्री सॉल्वर


22

केल्विन के शौक से यह समुदाय के लिए कई चुनौतियों में से एक है ।

प्रपत्र की पंक्तियों के साथ "पारिवारिक ट्री वर्णन" फ़ाइल लें:

[ID] [mother ID] [father ID] [gender] [full name]

इस तरह जो http://en.wikipedia.org/wiki/Cousin पर पहले परिवार के पेड़ का वर्णन करता है :

1 ? ? M Adam
2 ? ? F Agatha
3 ? ? M Bill
4 2 1 F Betty
5 2 1 M Charles
6 ? ? F Corinda
7 3 4 M David
8 6 5 F Emma

एक प्रोग्राम या फ़ंक्शन लिखें जो फ़ाइल नाम और दो आईडी में लेता है और आउटपुट करता है कि कैसे उन लोगों को संबंधों के लिए सामान्य अंग्रेजी नामों का उपयोग करते हुए, सरल शब्दों में रक्त-संबंधी हैं। इनपुट STDIN, ARGV या फ़ंक्शन तर्क के माध्यम से हो सकता है लेकिन आउटपुट STDOUT में होना चाहिए।

टिप्पणियाँ

  • आईडी सकारात्मक पूर्णांक हैं।
  • ? का उपयोग तब किया जाता है जब पेरेंटेज ज्ञात नहीं है।
  • मान लें कि ग्राफ जुड़ा होगा और कोई चक्र नहीं है।
  • आप यह नहीं मान सकते हैं कि प्रत्येक व्यक्ति के माता-पिता उस व्यक्ति से पहले सूचीबद्ध हैं (इसलिए किसी व्यक्ति की माता-पिता की आईडी उनकी अपनी आईडी से अधिक हो सकती है)।
  • मान लें कि हर कोई पुरुष या महिला है और सभी के पास ठीक एक मां और एक पिता (सही लिंग का) है, हालांकि वे अज्ञात हो सकते हैं।
  • मान लें कि नाम अद्वितीय हैं।
  • उनमें नाम स्थान हो सकते हैं।

रक्त संबंध

रिश्तों की निम्नलिखित परिभाषा आर निर्धारित करता है, तो व्यक्ति एक है आर या व्यक्ति बी । यदि R के दो वेरिएंट सूचीबद्ध हैं, तो पहला महिला A के लिए और दूसरा पुरुष A के लिए है । इन सभी को लागू करने की आवश्यकता है। यदि कई परिभाषाएं मेल खाती हैं, तो पहले वाले का उपयोग किया जाना है। कोष्ठक में शर्तें लिंग-तटस्थ शब्द हैं, जिन्हें लागू करने की आवश्यकता नहीं है, लेकिन आगे की परिभाषाओं में इसका पुन: उपयोग किया जाएगा। एन और एम से जुड़ी परिभाषाओं में , एन> 1 और एम> 0 मान लें ।

  • बेटी / बेटा: A सूची B को या तो माता-पिता के रूप में देखता है।
  • माता / पिता (माता-पिता): B, A को या तो माता-पिता के रूप में सूचीबद्ध करता है ।
  • बहन / भाई (भाई): A और B समान माता और पिता की सूची बनाते हैं।
  • सौतेली बहन / सौतेला भाई (भाई): A और B एक ही माँ या एक ही पिता को सूचीबद्ध करते हैं ।
  • भतीजी / भतीजे: एक सूचियों एक माता पिता कौन का भाई है बी
  • चाची / चाचा: बी है एक की भतीजी या भतीजे।
  • पोती / पोती (पोती): A एक ऐसे माता-पिता को सूचीबद्ध करता है जो B को उनके माता-पिता के रूप में सूचीबद्ध करता है ।
  • दादी / दादा (दादा-दादी): बी है एक के पोते।
  • महान-भतीजी / महान-भतीजा: A , C का पोता है जो B का भाई है ।
  • महान चाची / चाचा: बी है एक के महान-भतीजी या महान भतीजे।
  • पोती / बेटा (पहला परपोता): A , C का पोता है जो B को उनके माता-पिता के रूप में सूचीबद्ध करता है ।
  • परदादी / पिता (1 परदादा): बी है एक के 1 महान-पोते।
  • Nth great-granddaughter / son (Nth great-grandchild): A एक C (N-1) th पोता है, जो B को उनके माता-पिता के रूप में सूचीबद्ध करता है ।
  • Nth महान-दादी / पिता (Nth great-grandparent): B A का Nth परदादा है ।
  • वां महान-भतीजी / भतीजे: एक है (एन 1) के वें महान-पोते सी जो की भाई है बी
  • वां महान चाची / चाचा: बी है एक की वां वां महान भतीजे के महान-भतीजी।
  • cousin: A , C का पोता है जो B का दादा है ।
  • Nth cousin: A , N का (N-1) th पोता है, जो B का N (N-1) वें दादा-दादी है ।
  • चचेरे भाई, एम बार हटाया: एक के पोता है सी जो की महीना दादा-दादी है बी या एक का महीना पोता है सी जो की दादा-दादी है बी
  • Nth चचेरे भाई, एम बार हटा दिया गया: A , C का Pth महा-पोता है, जो B का Qth परदादा है , जहां N = min(P,Q) + 1और M = |P-Q|

के लिए Nth, लिखने 2nd, 3rd, 4th, 5thआदि

के लिए M times, लिखने once, twice, thrice, 4 times, 5 timesआदि

उदाहरण

मान लें कि निम्न फ़ाइल का उपयोग किया गया है (आपको कई स्थानों से निपटने में सक्षम होने की आवश्यकता नहीं है, लेकिन मैंने उन्हें उपयुक्तता के लिए जोड़ा है):

 1  ?  ? F Agatha
 2  ?  ? M Adam
 3  ?  ? F Betty
 4  1  2 M Bertrand
 5  1  2 F Charlotte
 6  ?  ? M Carl
 7  ?  ? F Daisy
 8  3  4 M David
 9  5  6 F Emma
10  ?  ? M Edward
11  ?  ? F Freya
12  7  8 M Fred
13  9 10 F Grace
14  ?  ? M Gerald
15  ?  ? F Hillary
16 11 12 M Herbert
17 13 14 F Jane
18  ?  ? M James
19 15 16 F Kate
20 17 18 M Larry
21  ? 18 F Mary

फिर इनपुट आईडी को निम्नानुसार आउटपुट के लिए मैप करना चाहिए:

 1  2 --> Agatha is not a blood relative to Adam.
 8  3 --> David is the son of Betty.
 9 13 --> Emma is the mother of Grace.
 4  5 --> Bertrand is the brother of Charlotte.
 9  4 --> Emma is the niece of Bertrand.
 5  8 --> Charlotte is the aunt of David.
16  7 --> Herbert is the grandson of Daisy.
 1  9 --> Agatha is the grandmother Emma.
12  5 --> Fred is the great-nephew of Charlotte.
 4 13 --> Bertrand is the great-uncle of Grace.
16  3 --> Herbert is the great-grandson of Betty.
 6 17 --> Carl is the great-grandfather of Jane.
19  2 --> Kate is the 3rd great-granddaughter of Adam.
 1 17 --> Agatha is the 2nd great-grandmother of Jane.
20  4 --> Larry is the 3rd great-nephew of Bertrand.
 5 16 --> Charlotte is the 2nd great-aunt of Herbert.
 8  9 --> David is the cousin of Emma.
19 20 --> Kate is the 4th cousin of Larry.
16  9 --> Herbert is the cousin, twice removed, of Emma.
12 17 --> Fred is the 2nd cousin, once removed, of Jane.
21 20 --> Mary is the half-sister of Larry.

मैंने उन लोगों को हाथ से लिखा है इसलिए मुझे बताएं कि क्या आप कोई गलती करते हैं।

परीक्षण डेटा का एक और सेट (स्कॉट लीडले द्वारा प्रदान किया गया, कोई भी त्रुटियां मेरी हैं और मार्टिन की नहीं)
टॉलेमी परिवार का पेड़ टॉलेमी परिवार का पेड़
चित्र आकर्षक है; नीचे दिया गया डेटा विकिपीडिया लेख " टॉलेमिक वंश " से आया है।

 1  ?  ? F Berenice I of Egypt
 2  ?  ? M Ptolemy I Soter
41  1  2 F Arsinoe II of Egypt
 3  1  2 M Ptolemy II Philadelphus
 4  ?  ? F Arsinoe I of Egypt
 5  ?  ? M Philip
 6  4  3 M Ptolemy III Euergetes
 7  1  5 F Magas of Cyrene
 8  7  ? F Berenice II
 9  8  6 M Ptolemy IV Philopator
10  8  6 F Arsinoe III of Egypt
11 10  9 M Ptolemy V Epiphanes
12  ?  ? F Cleopatra I of Egypt
13 12 11 M Ptolemy VI Philometor
14 12 11 F Cleopatra II
15 12 11 M Ptolemy VIII Physcon
19  ?  ? F Eirene
16 14 13 M Ptolemy VII Neos Philopator
17 14 13 F Cleopatra III
18 14 15 M Ptolemy Memphites
20 19 15 M Ptolemy Apion
21 17 15 F Cleopatra IV
22 17 15 M Ptolemy IX Lathyros
23 17 15 F Cleopatra Selene I
24 17 15 M Ptolemy X Alexander I
25 23 22 F Berenice III of Egypt
26 23 24 M Ptolemy XI Alexander II
27 21 22 M Ptolemy XII Auletes
28 25 24 F Cleopatra V of Egypt
29 28 27 F Cleopatra VI of Egypt
30 28 27 F Berenice IV of Egypt
31 28 27 M Ptolemy XIII Theos Philopator
32 28 27 F Cleopatra VII Thea Philopator
33 28 27 M Ptolemy XIV
34 28 27 F Arsinoe IV of Egypt
35  ?  ? M Julius Caesar
37 32 35 M Ptolemy XV Caesarion
36  ?  ? M Mark Anthony
38 32 36 M Alexander Helios
39 32 36 M Ptolemy XVI Philadelphus
40 32 36 F Cleopatra Selene II

जवाबों:


3

ईसीएमएस्क्रिप्ट 6, 886

शून्य से विभाजन एक अद्भुत चीज है।

यह एक बार अर्ध-शाब्दिक का उपयोग करता है (जो फ़ायरफ़ॉक्स 33 या नोड.जेएस में लागू नहीं होते हैं, लेकिन फ़ायरफ़ॉक्स के रात के निर्माण में उपलब्ध हैं )। अर्ध शाब्दिक का इस्तेमाल किया:

`
`

"\n"यदि आप जो कुछ भी इनका उपयोग कर रहे हैं, उसके साथ प्रतिस्थापित किया जा सकता है ।

यह स्क्रिप्ट माता-पिता और बच्चों दोनों को संग्रहीत करते हुए लोगों की सूची से एक पेड़ का निर्माण करती है। व्यक्ति A से व्यक्ति B तक के प्रत्येक पथ को आज़माया जाता है, और इष्टतम पथ सहेजा जाता है। एक पथ को वैध माना जाता है यदि यह केवल एक बार पेड़ से नीचे जाने के लिए बदल जाता है। विपरीत परिवर्तन की अनुमति नहीं है - यदि किसी को एक बच्चे को नीचे जाने और एक रास्ता खोजने के लिए दूसरे माता-पिता के पास वापस जाने की आवश्यकता है, तो दो लोग रक्त रिश्तेदार नहीं हैं। ( UUUUUDDDवैध है, UUDUUUनहीं है। Uमतलब ऊपर (एक माता-पिता के लिए), Dमतलब नीचे जाना (एक बच्चे के लिए)।

गोल्फ की तरह:

R=(a,b)=>{F="forEach",C='';p=[],g=[],c={},n=[],e=m=1/0;y=i=>i+(k=i%10,k&&k<4&&~~(i%100/10)-1?[,'st ','nd ','rd '][k]:'th ');q=(a,b,s,$)=>!($=$.slice())|!a|~$.indexOf(a)||a-b&&$.push(a)|[p,c][F]((M,N)=>M[a][F](j=>q(j,b,s+N,$)))||(z=(s.match(/0/g)||[]).length,r=s.length-z,_=e+m-z-r,s.indexOf(10)<0&_>0|!_&m>r&&(e=z,m=r));I.split(`
`)[F](V=>{P=V.split(' ');D=+P[0];p[D]=[+P[1],+P[2]];g[D]=P[3]<'L';n[D]=P.slice(4).join(' ');c[D]=[]});p[F]((V,I)=>V[F](Y=>Y&&c[Y].push(I)));q(a,b,C,[]);U=e>m?m:e,V=e>m?e:m;alert(n[a]+' is '+(e/m+1?'the '+(U*V---1?U<2?(V<3?C:y(V-1))+(V<2?C:'great-')+(V*!U?'grand':C)+'son0father0nephew0uncle0daughter0mother0niece0aunt'.split(0)[g[a]*4+2*U+(U==e)]:(V-=--U,(U<2?C:y(U))+'cousin'+(V?', '+(V>3?V+' times':[,'on','twi','thri'][V]+'ce')+' removed,':C)):(p[a].join()==p[b].join()?C:'half-')+(g[a]?'sister':'brother'))+' of ':'not a blood relative to ')+n[b]+'.')}

अघोषित (तरह का):

// function for running.
R=(a,b)=>{
F="forEach",C='';
p=[], g=[], c={}, n=[], e=m=1/0;
// returns suffixed number (1->1st, 2->2nd, etc)
y= i=>i+(k=i%10,k&&k<4&&~~(i%100/10)-1?[,'st ','nd ','rd '][k]:'th ');
// this looks for the shortest path up/down the family tree between a and b.
q=(a,b,s,$)=>
  // copy the array of visited people
  !($=$.slice())
  // check if a is invalid
  | !a
  // check to make sure we are not visiting a for a second time
  | ~$.indexOf(a)
  // if a != b
  || a-b 
  // add a to visited, and call q(...) on all parents and children
  && $.push(a) |
   [p,c][F]((M,N)=>M[a][F](j=>q(j,b,s+N,$)))
  || (
    // a == b
    // get number of ups and downs
    z=(s.match(/0/g)||[]).length,
    r=s.length-z,

    _=e+m-z-r,
    // if DU: path is invalid.
    // if _>0: path is shorter
    // if _==0: check m > r to see if new path should replace old 
    s.indexOf(10)<0 & _>0|!_&m>r && (e=z,m=r));
// load list of people into arrays
I.split(`
`)[F](V=>{
  P=V.split(' ');
  // ID
  D=+P[0];
  // parents: NaN if not given
  p[D]=[+P[1],+P[2]];
  // gender: 1 if female, 0 if male
  g[D]=P[3]<'L';
  // merge the rest of the array to get name
  n[D]=P.slice(4).join(' ');
  // empty children array..for now
  c[D]=[]
});
// push current ID to parents' children array.
p[F]((V,I)=>V[F](Y=>Y&&c[Y].push(I)));

// get shortest path
q(a,b,C,[]);

U=e>m?m:e,V=e>m?e:m;
G=(a,b,c,d)=>(a<3?C:y(a-1))+(a<2?C:'great-')+(a*!b?'grand':C)+'son0father0nephew0uncle0daughter0mother0niece0aunt'.split(0)[g[d]*4+2*b+(b==c)];


// output
alert(n[a]+' is '+(e/m+1?'the '+(U*V---1?
    U<2?
        G(V,U,e,a)
    :(V-=--U,
     (U<2?C:y(U))+'cousin'+
     (V?
        ', '+(V>3?V+' times':[,'on','twi','thri'][V]+'ce')+' removed,'
     :C)
     )
:(p[a].join()==p[b].join()?C:'half-')+(g[a]?'sister':'brother'))+' of ':'not a blood relative to ')+n[b]+'.')
}

टिप्पणियाँ:

  • लोगों की सूची को एक चर में रखा जाना चाहिए I(एक स्ट्रिंग के रूप में, एकल रिक्त स्थान और newlines के साथ)।
  • कॉल करने के लिए: दो लोगों की तुलना R(a,b)कहां aऔर bकिस आईडी से की जा रही है।

5

कोबरा - 932

कोबरा में मैंने जिन भी चुनौतियों का जवाब दिया है, उनमें से यह अब तक के सबसे अच्छे उदाहरणों में से एक है।

संपादित करें: यह अब एक फ़ंक्शन है, लेकिन Z (चार गिनती में शामिल) के लिए हस्ताक्षर द्वारा उपसर्ग किया जाना चाहिए।

sig Z(m,n=nil,r=nil)as String?
def f(f='',u='',v='')
    d={:}
    for l in File.readAllLines(f)
        w=l.trim.split
        i,j,k,p=w[:4]
        q=w[4:].join(' ')
        if i==u,x,g=q,if(p<'M',1,0)
        if i==v,y=q
        d.add(i,[j,k])
    o as Z=do(n,m,r)=if(n>1,"[n][if(0<n%10<4and not 10<n%100<14,'stndrd'[n%10-1:n%10+2],'th')] ",'')
    z as Z=do(m,n,r)
        h,a,b=n
        if m[0]==m[1]
            if if(b<1or 0<b<3and a>b,s=2,s=0),a,b=b,a
            r="the [if(a,if(a<2,if(b<2,if(not'?'in'[c=d[u]][e=d[v]]'and c==e,'','half-')+['brother','sister'][g],if(b<3,'',o(b-2)+'great-')+['uncle','aunt','nephew','neice'][s+g]),o(a-1)+'cousin'+if(b>a,', '+if((b-=a)<4,['on','twi','thri'][b-1]+'ce','[b] times')+' removed,','')),if(b,if(b<3,'',o(b-2)+'great-')+'grand','')+['father','mother','son','daughter'][s+g])] of"
        for t in d[m[h]],if'?'<>h,r?=if(h,z([m[0],t],[1,a,b+1]),z(m,[1,a,0])?z([t,v],[0,a+1,0]))
        return r to String?
    print x+" is [z([u,v],[0,0,0])?'not a blood relative to'] [y]."

टिप्पणी की: (तारीख से बाहर, लेकिन अभी भी एक ही कोड-प्रवाह)

class F
    # Initilaise link dict
    var d={'?':@[''][:0]}
    # Gender bool
    var g
    def main
        # Initilaise name dict
        d={'?':@[''][:0]}
        # Take args
        f,a,b=CobraCore.commandLineArgs[1:]
        # For line in file
        for l in File.readAllLines(f)
            # Split line
            i=l.split
            # Add links to link dict
            .d.add(i[0],i[1:3])
            # Add names to name dict
            d.add(i[0],i[3:])
        # Get gender
        .g=if(d[a][0]=='F',1,0)
        # Print result
        print _
            '[d[a][1]] is '+ _ # Name A
                .r(@[1,0,0],@[a,a,b,b]) _ # If link found, link
                ? _ # Else
                'not a blood relative'+ _ # Not related
            ' of [d[b][1]].' # Name B
    def r(n as int[],m as String[])as String?
        # Recurse through the links at each level from A (A1), climbing when no links are found to B
        # For each level incremented for A, search upwards to the end of all nodes from B (B1), looking for A1
        r=nil
        # Check if we're done searching/climbing
        if m[1]==m[2]
            a,b=n[1:]
            s=if(b<1or b in[1,2]and a>b,1,0)
            if s,a,b=b,a
            # Take the A and B distance and translate them into a phrase
            return'the '+ _ 
                if(a, _
                    if(a<2, _
                        if(b<2, _
                            if('?'not in'[.d[m[0]]][.d[m[3]]]'and.d[m[0]]==.d[m[3]], _
                                '', _
                                'half-' _
                            )+['brother','sister'][.g], _
                            if(b<3, _
                                '', _
                                .o(b-2)+'great-' _
                            )+[['uncle','aunt'],['nephew','neice']][s][.g] _
                        ), _
                        .o(a-1)+'cousin'+if(b>a, _
                            ', '+if((b-=a)<4, _
                                ['once','twice','thrice'][b-1], _
                                '[b] times' _
                            )+' removed,', _
                            '' _
                        ) _
                    ), _
                    if(b, _
                        if(b<3, _
                            '', _
                            '[.o(b-2)]great-' _
                        )+'grand', _
                        '' _
                    )+[['father','mother'],['son','daughter']][s][.g] _
                )
        # Check if we're climbing
        if n[0]
            # For each link in the current A-level
            for x in.d[m[1]]
                r?= _
                    .r(@[0,n[1],0],m) _ # Start a search
                    ? _ # If the search failed
                    .r(@[1,n[1]+1,0],@[m[0],x,m[3],m[3]]) # Climb again
        # Check if we're searching
        else
            # For each link in the current B-level
            for x in.d[m[2]]
                # Search up one level from the current B-level
                r?=.r(@[0,n[1],n[2]+1],@[m[0],m[1],x,m[3]])
        return r
    def o(n as int)as String
        # Get ordinal string for the number
        return if(n>1,'[n][if(0<n%10<4and not 10<n%100<14,['st','nd','rd'][n%10-1],'th')] ','')

3

ग - अपुष्ट

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

typedef enum {
    MALE,
    FEMALE
} gender_t;

typedef enum {
    VISITED_A,
    VISITED_B,
    NOT_VISITED
} visited_t;

struct node {
    int id;
    int mother;
    int father;
    char *name;
    int height;
    gender_t gender;
    visited_t visited;
};

struct queue_item {
    void *item;
    struct queue_item *next;
    struct queue_item *previous;
};

struct queue {
    struct queue_item *first;
    struct queue_item *last;
};

void queue_push(struct queue *q, struct node *n)
{
    struct queue_item *i = malloc(sizeof(*i));
    i->item = (void *)n;
    i->next = q->last;
    i->previous = NULL;
    q->last = i;
    if(i->next != NULL) {
        i->next->previous = i;
    } else {
        q->first = i;
    }
}

void queue_pop(struct queue *q)
{
    struct queue_item *temp = q->first;
    if(temp) {
        q->first = q->first->previous;
        if(q->first == NULL) {
            q->last = NULL;
        } else {
            q->first->next = NULL;
        }
        free(temp);
    }
}

struct node *queue_front(struct queue *q)
{
    if(q->first) {
        return (struct node *)q->first->item;
    } else {
        return NULL;
    }
}

void queue_free(struct queue *q) {
    while(queue_front(q) != NULL) {
        queue_pop(q);
    }

    free(q);
}

struct node *find_shortest_path(struct node **nodes, struct node *a, struct node *b)
{

    struct queue *q = malloc(sizeof(*q));
    q->first = NULL;
    q->last = NULL;

    a->visited = VISITED_A;
    queue_push(q, a);
    b->visited = VISITED_B;
    queue_push(q, b);

    struct node *n, *father, *mother;

    while((n = queue_front(q)) != NULL) {
        if(n->visited == VISITED_A) {
            if(n->father != 0) {
                father = nodes[n->father-1];
                if(father->visited == VISITED_B) {
                    a->height = n->height + 1;
                    b->height = father->height;
                    n = father;
                    goto exit_queue_free;
                } else  if(father->visited == NOT_VISITED) {
                    father->visited = VISITED_A;
                    father->height = n->height+1;
                    queue_push(q, father);
                }
            }
            if(n->mother != 0) {
                mother = nodes[n->mother-1];
                if(mother->visited == VISITED_B) {
                    a->height = n->height + 1;
                    b->height = mother->height;
                    n = mother;
                    goto exit_queue_free;
                } else  if(mother->visited == NOT_VISITED) {
                    mother->visited = VISITED_A;
                    mother->height = n->height+1;
                    queue_push(q, mother);
                }
            }
        } else if (n->visited == VISITED_B) {
            if(n->father != 0) {
                father = nodes[n->father-1];
                if(father->visited == VISITED_A) {
                    b->height = n->height + 1;
                    a->height = father->height;
                    n = father;
                    goto exit_queue_free;
                } else  if(father->visited == NOT_VISITED) {
                    father->visited = VISITED_B;
                    father->height = n->height+1;
                    queue_push(q, father);
                }
            }
            if(n->mother != 0) {
                mother = nodes[n->mother-1];
                if(mother->visited == VISITED_A) {
                    b->height = n->height + 1;
                    a->height = mother->height;
                    n = mother;
                    goto exit_queue_free;
                } else  if(mother->visited == NOT_VISITED) {
                    mother->visited = VISITED_B;
                    mother->height = n->height+1;
                    queue_push(q, mother);
                }
            }
        }

        queue_pop(q);
    }

exit_queue_free:
    queue_free(q);
    return n;
}

int main(int argc, char *argv[]) {

    if(argc != 4) {
        return -1;
    }

    FILE *file = fopen(argv[1], "r");
    int id_1 = strtol(argv[2], NULL, 0);
    int id_2 = strtol(argv[3], NULL, 0);

    char name[128];
    char id[128];
    char id_father[128];
    char id_mother[128];
    char gender;

    struct queue *read_queue = malloc(sizeof(*read_queue));
    read_queue->first = NULL;
    read_queue->last = NULL;
    int nr_nodes = 0;

    while(fscanf(file, "%s %s %s %c %s",
        id, id_mother, id_father, &gender, name) == 5) {

        struct node *n = malloc(sizeof(*n));
        if(strcmp(id, "?") == 0) {
            n->id = 0;
        } else {
            n->id = strtol(id, NULL, 0);
        }

        if(strcmp(id_mother, "?") == 0) {
            n->mother = 0;
        } else {
            n->mother = strtol(id_mother, NULL, 0);
        }

        if(strcmp(id_father, "?") == 0) {
            n->father = 0;
        } else {
            n->father = strtol(id_father, NULL, 0);
        }

        if(gender == 'M') {
            n->gender = MALE;
        } else {
            n->gender = FEMALE;
        }

        n->name = malloc(strlen(name)+1);

        strcpy(n->name, name);

        n->visited = NOT_VISITED;
        n->height = 0;

        queue_push(read_queue, n);

        nr_nodes++;
    }

    struct node **nodes = malloc(sizeof(*nodes) * nr_nodes);
    struct node *temp;
    while((temp = queue_front(read_queue)) != NULL) {
        nodes[temp->id-1] = temp;
        queue_pop(read_queue);
    }

    queue_free(read_queue);

    struct node *a = nodes[id_1-1], *b = nodes[id_2-1];

    temp = find_shortest_path(nodes, a, b);

    if(temp) {
        if(a->height == b->height) {
            if(a->height == 1) {
                if((a->father == b->father) &&
                    (a->mother == b->mother)) {
                    printf("%s is the %s of %s.\n", a->name,
                        a->gender == MALE ?
                        "brother" : "sister",
                        b->name);
                } else {
                    printf("%s is the half-%s of %s.\n",
                        a->name,
                        a->gender == MALE ?
                        "brother" : "sister",
                        b->name);
                }
            } else if (a->height == 2) {
                printf("%s is the cousin of %s.\n", a->name,
                    b->name);
            } else if (a->height == 3){
                printf("%s is the 2nd cousin of %s.\n", a->name,
                    b->name);
            } else if (a->height == 4) {
                printf("%s is the 3rd cousin of %s.\n", a->name,
                    b->name);
            } else {
                printf("%s is the %dth cousin of %s.\n", a->name,
                    a->height-1,b->name);
            }
        } else if (a->height == 0) {
            if(b->height == 1) {
                printf("%s is the %s of %s.\n", a->name,
                    a->gender == MALE ? "father" :
                    "mother", b->name);
            } else if (b->height == 2) {
                printf("%s is the grand%s of %s.\n", a->name,
                    a->gender == MALE ? "father" :
                    "mother", b->name);
            } else if (b->height == 3) {
                printf("%s is the great-grand%s of %s.\n",
                    a->name, a->gender == MALE ?
                    "father" : "mother", b->name);
            } else if (b->height == 4) {
                printf("%s is the 2nd great-grand%s of %s.\n",
                    a->name, a->gender == MALE ?
                    "father" : "mother", b->name);
            } else if (b->height == 5) {
                printf("%s is the 3rd great-grand%s of %s.\n",
                    a->name, a->gender == MALE ?
                    "father" : "mother", b->name);
            } else if (b->height == 6) {
                printf("%s is the %dth great-grand%s of %s.\n",
                    a->name, b->height-2,
                    a->gender == MALE ? "father" :
                    "mother", b->name);
            }
        } else if (b->height == 0) {
            if(a->height == 1) {
                printf("%s is the %s of %s.\n", a->name,
                    a->gender == MALE ? "son" :
                    "daughter", b->name);
            } else if (a->height == 2) {
                printf("%s is the grand%s of %s.\n", a->name,
                    a->gender == MALE ? "son" :
                    "daughter", b->name);
            } else if (a->height == 3) {
                printf("%s is the great-grand%s of %s.\n",
                    a->name, a->gender == MALE ?
                    "son" : "daughter", b->name);
            } else if (a->height == 4) {
                printf("%s is the 2nd great-grand%s of %s.\n",
                    a->name, a->gender == MALE ?
                    "son" : "daughter", b->name);
            } else if (a->height == 5) {
                printf("%s is the 3rd great-grand%s of %s.\n",
                    a->name, a->gender == MALE ?
                    "son" : "daughter", b->name);
            } else {
                printf("%s is the %dth great-grand%s of %s.\n",
                    a->name, a->height - 2,
                    a->gender == MALE ? "son" :
                    "daughter", b->name);
            }
        } else if (a->height == 1) {
            if(b->height == 2) {
                printf("%s is the %s of %s.\n", a->name,
                    a->gender == MALE ? "uncle" :
                    "aunt", b->name);
            } else if(b->height == 3) {
                printf("%s is the great-%s of %s.\n", a->name,
                    a->gender == MALE ? "uncle" :
                    "aunt", b->name);
            } else if(b->height == 4) {
                printf("%s is the 2nd great-%s of %s.\n", a->name,
                    a->gender == MALE ? "uncle" :
                    "aunt", b->name);
            } else if(b->height == 5) {
                printf("%s is the 3rd great-%s of %s.\n", a->name,
                    a->gender == MALE ? "uncle" :
                    "aunt", b->name);
            } else {
                printf("%s is the %dth great-%s of %s.\n",
                    a->name, b->height - 2,
                    a->gender == MALE ? "uncle" :
                    "aunt", b->name);
            }
        } else if (b->height == 1) {
            if(a->height == 2) {
                printf("%s is the %s of %s.\n", a->name,
                    a->gender == MALE ? "nephew" :
                    "niece", b->name);
            } else if(a->height == 3) {
                printf("%s is the great-%s of %s.\n", a->name,
                    a->gender == MALE ? "nephew" :
                    "niece", b->name);
            } else if(a->height == 4) {
                printf("%s is the 2nd great-%s of %s.\n", a->name,
                    a->gender == MALE ? "nephew" :
                    "niece", b->name);
            } else if(a->height == 5) {
                printf("%s is the 3rd great-%s of %s.\n", a->name,
                    a->gender == MALE ? "nephew" :
                    "niece", b->name);
            } else {
                printf("%s is the %dth great-%s of %s.\n",
                    a->name, a->height - 2,
                    a->gender == MALE ? "nephew" :
                    "niece", b->name);
            }
        } else {
            int m = a->height > b->height ? a->height - b->height :
                b->height - a->height;
            int n = a->height > b->height ? b->height - 1:
                a->height - 1;

            printf("%s is the ", a->name);
            if(n == 2) printf("2nd ");
            if(n == 3) printf("3rd ");
            if(n > 3) printf("%dth ", n);
            printf(" cousin, ");
            if (m == 1) printf("once");
            if (m == 2) printf("twice");
            if (m == 3) printf("thrice");
            if (m > 3) printf("%d times", m);
            printf(" removed, of %s.\n", b->name);
        }
    } else
        printf("%s is not a blood relative to %s.\n", a->name, b->name);



    int i;
    for(i = 0; i < nr_nodes; i++) {
        free(nodes[i]->name);
        free(nodes[i]);
    }

    free(nodes);

    fclose(file);

    return 0;
}

क्या दिज्क्स्ट्रा का सबसे छोटा पथ एल्गोरिथम का कार्यान्वयन बीच में छिपा है?
स्कॉट लेडले

हां, यह दिज्क्स्ट्रा का सबसे छोटा रास्ता है। यह एक डीजस्ट्रा उदाहरण ए और एक बी से शुरू होता है और दोनों खोजों के पूरा होने पर समाप्त हो जाता है।
Optokopper

3

माणिक - 1892 1290 1247

ऐसे दोड़ो ruby relation.rb ID1 ID2 relationship_file

P=Struct.new(:i,:m,:f,:s,:n,:c)
def f u,v,w,x,y,z
t=[y,z,v]
return t if v=='?'||x.include?(v)||v==w
r=x+[v];p=u[v]
p.c.each{|o|s=f(u,o,w,r,y,z+1);return s if s.last==w}
return t if z>0
[:m,:f].each{|i|s=f(u,p[i],w,r,y+1,z);return s if s.last==w}
t;end
def g j,a,r,b;puts"#{j[a].n} is the #{r} of #{j[b].n}.";end
def k n;n<2?'':n<3?'2nd':n<4?'3rd':"#{n}th";end
def h n;n<2?'':n<3?'great-':"#{k(n-1)} great-";end
def e n;s=n<2?'once':n<3?'twice':n<4?'thrice':"#{n} times";", #{s} removed,";end
def d u,a,b,x;y,z=x
if y==1&&z==1
w=u[a];v=u[b]
g(u,a,((w.f==v.f&&w.m==v.m)?'':'half-')+((w.s=='F')?'sister':'brother'),b)
elsif y<1||z<1
t=[y,z].max
g(u,a,h(t-1)+(t>=2?'grand':'')+(u[a].s=='F'?y>0?'daughter':'mother':y>0?'son':'father'),b)
elsif y==1||z==1
t=[y,z].max
g(u,a,h(t-1)+(u[a].s=='F'?y==1?'aunt':'niece':y==1?'uncle':'nephew'),b)
else
s=[y,z].min
g(u,a,(s-1>1?"#{k(s-1)} ":'')+'cousin'+((y==z)?'':e((z-y).abs)),b)
end;end
A,B=$*.shift(2);j={}
ARGF.each_line{|l|a=l.scan(/\s*(\d+)\s+(\d+|\?)\s+(\d+|\?)\s+([MF])\s+([\w\s]*\w+)\s*/).flatten;j[a[0]]=P.new(a[0],a[1],a[2],a[3],a[4],[])}
j.each{|k,i|[:f,:m].each{|l|j[i[l]].c<<k if i[l]!='?'}}
a=f(j,A,B,[],0,0)
if a.pop==B
d(j,A,B,a)
else
puts"#{j[A].n} is not a blood relative to #{j[B].n}."

Ungolfed संस्करण - 5251 3416 (एक ही कॉल ट्री, बस बहुत सारे कोड फोल्डिंग)

Person = Struct.new( :id, :mother, :father, :sex, :name, :children )

#       Find a path between "start" and "finish". To reflect human consanguinity
# rules, either travel down through descendants or up through ancestors with a
# possible down leg through their descendants.
#
# Use depth-first search until forced to improve.
# If start up, path allowed one inflection point.
# Once start down, path must continue down.
# returns [stepsUp, stepsDown, trialResult],
#   shortest path found if trialResult == finish
def findRelationship(people, start, finish, pathSoFar, stepsUp, stepsDown)
  trialResult = [stepsUp, stepsDown, start]
  #     Return success or failure.
  return trialResult if start == '?' || pathSoFar.include?(start) || start == finish
  #     If success or failure not known, explore further.
  pathNext = pathSoFar + [start]
  person = people[start]
  #     Follow descendants.
  person[:children].each do |child|
    trial = findRelationship(people, child, finish, pathNext, stepsUp, stepsDown+1)
    return trial  if trial.last == finish
  end
  #     Already past inflection point?
  return trialResult  if stepsDown > 0
  #     Follow ancestry.
  [:mother, :father].each do |parent|
    trial = findRelationship(people, person[parent], finish, pathNext, stepsUp+1, stepsDown)
    return trial  if trial.last == finish
  end
  return trialResult
end

def printRelationship(people, a, relationship, b)
  puts "#{people[a][:name]} is the #{relationship} of #{people[b][:name]}."
end

def formatNth(n)
  return n<2?'':n<3?'2nd':n<4?'3rd':"#{n}th"
end

def formatGenerations(n)
  return n<2?'':n<3?'great-':"#{formatNth(n-1)} great-"
end

def formatRemoves(n)
  s=n<2?'once':n<3?'twice':n<4?'thrice':"#{n} times"
  return ", #{s} removed,"
end

def describeRelationship(people, a, b, legLengths)
  down = legLengths.pop
  up = legLengths.pop
  if up==1 && down==1
    who = people[a]
    what = people[b]
    printRelationship(people, a,
        (who[:father] == what[:father]  &&  who[:mother] == what[:mother] ? '' : 'half-') +
          ((who[:sex] == 'F') ? 'sister' : 'brother'),
        b)
  elsif up<1 || down<1
    pathLength = [up, down].max
    printRelationship(people, a,
        formatGenerations(pathLength-1) + ((pathLength>=2) ? 'grand' : '') +
          (up>0 ?
            people[a][:sex] == 'F' ? 'daughter' : 'son'  :
            people[a][:sex] == 'F' ? 'mother': 'father'
          ),
        b)
  elsif up==1 || down==1
    pathLength = [up, down].max
    printRelationship(people, a,
        formatGenerations(pathLength-1) +
          (up==1 ?
            people[a][:sex] == 'F' ? 'aunt': 'uncle'  :
            people[a][:sex] == 'F' ? 'niece': 'nephew'
          ),
        b)
  else
    shortestLeg = [up, down].min
    printRelationship(people, a,
        (shortestLeg-1>1 ? "#{formatNth(shortestLeg-1)} " : '') +
          'cousin' +
          (up==down ? '' : formatRemoves((down-up).abs)),
        b)
  end
end

A = $*.shift
B = $*.shift
#       Meet and greet.
people = {}
ARGF.each_line do |line|
  a = line.scan(/\s*(\d+)\s+(\d+|\?)\s+(\d+|\?)\s+([MF])\s+([\w\s]*\w+)\s*/).flatten
  people[a[0]] = Person.new( a[0], a[1], a[2], a[3], a[4], [] )
end
#       Build lineage.
people.each do |key, individual|
  [:father, :mother].each do |l|
      people[individual[l]][:children] << key  if individual[l] != '?'
  end
end
#       How are A and B related?
a = findRelationship(people, A, B, [], 0, 0)
if a.pop == B
  describeRelationship(people, A, B, a)
else
  puts "#{people[A][:name]} is not a blood relative to #{people[B][:name]}."
end

निम्नलिखित परीक्षण सूट पास करता है:

#!/usr/bin/env perl
#
use strict;
use warnings;
require File::Temp;
use File::Temp qw( tempfile tempdir );

use Test::More qw(no_plan);
# use Test::More tests => 38;


#       solution executable
my $solver='ruby relation.rb';


#       "happy" path
my $dir = tempdir( CLEANUP => 1 );
my ($fh, $filename) = tempfile( DIR => $dir );
my $testData = <<'END_TEST_DATA';
 1  ?  ? F Agatha
 2  ?  ? M Adam
 3  ?  ? F Betty
 4  1  2 M Bertrand
 5  1  2 F Charlotte
 6  ?  ? M Carl
 7  ?  ? F Daisy
 8  3  4 M David
 9  5  6 F Emma
10  ?  ? M Edward
11  ?  ? F Freya
12  7  8 M Fred
13  9 10 F Grace
14  ?  ? M Gerald
15  ?  ? F Hillary
16 11 12 M Herbert
17 13 14 F Jane
18  ?  ? M James
19 15 16 F Kate
20 17 18 M Larry
21  ? 18 F Mary
END_TEST_DATA
print $fh  $testData;
close($fh);

is( `$solver 1  2 $filename 2>&1`, "Agatha is not a blood relative to Adam.\n", 'OP example #1,  1  2');
is( `$solver 8 3 $filename 2>&1`, "David is the son of Betty.\n", 'OP example #2,  8  3');
is( `$solver 9 13 $filename 2>&1`, "Emma is the mother of Grace.\n", 'OP example #3,  9 13');
is( `$solver 4 5 $filename 2>&1`, "Bertrand is the brother of Charlotte.\n", 'OP example #4,  4  5');
is( `$solver 9 4 $filename 2>&1`, "Emma is the niece of Bertrand.\n", 'OP example #5,  9  5');
is( `$solver 5 8 $filename 2>&1`, "Charlotte is the aunt of David.\n", 'OP example #6,  5  8');
is( `$solver 16 7 $filename 2>&1`, "Herbert is the grandson of Daisy.\n", 'OP example #7, 16  7');
is( `$solver 1 9 $filename 2>&1`, "Agatha is the grandmother of Emma.\n", 'OP example #8,  1  9 (amended)');
is( `$solver 12 5 $filename 2>&1`, "Fred is the great-nephew of Charlotte.\n", 'OP example #9, 12  5');
is( `$solver 4 13 $filename 2>&1`, "Bertrand is the great-uncle of Grace.\n", 'OP example #10,  4 13');
is( `$solver 16 3 $filename 2>&1`, "Herbert is the great-grandson of Betty.\n", 'OP example #11, 16  3');
is( `$solver 6 17 $filename 2>&1`, "Carl is the great-grandfather of Jane.\n", 'OP example #12,  6 17');
is( `$solver 19 2 $filename 2>&1`, "Kate is the 3rd great-granddaughter of Adam.\n", 'OP example #13, 19  2 (amended)');
is( `$solver 1 17 $filename 2>&1`, "Agatha is the 2nd great-grandmother of Jane.\n", 'OP example #14,  1 17 (amended)');
is( `$solver 20 4 $filename 2>&1`, "Larry is the 3rd great-nephew of Bertrand.\n", 'OP example #15, 20  4');
is( `$solver 5 16 $filename 2>&1`, "Charlotte is the 2nd great-aunt of Herbert.\n", 'OP example #16,  5 16');
is( `$solver 8 9 $filename 2>&1`, "David is the cousin of Emma.\n", 'OP example #17,  8  9');
is( `$solver 19 20 $filename 2>&1`, "Kate is the 4th cousin of Larry.\n", 'OP example #18, 19 20');
is( `$solver 16 9 $filename 2>&1`, "Herbert is the cousin, twice removed, of Emma.\n", 'OP example #19, 16  9');
is( `$solver 12 17 $filename 2>&1`, "Fred is the 2nd cousin, once removed, of Jane.\n", 'OP example #20, 12 17');
is( `$solver 21 20 $filename 2>&1`, "Mary is the half-sister of Larry.\n", 'OP example #21, 21 20');


#       "sad" path
# none!


#       "bad" path
# none!


exit 0;

2

जावास्क्रिप्ट, 2292

for(var r=prompt().split("\n"),n=[{m:"",f:""}],t=1;t<r.length;t++){var e=r[t].split(" ");n[+e[0]]={m:"?"==e[1]?-1:+e[1],f:"?"==e[2]?-1:+e[2],s:e[3],n:e[4]}}var f=function(r,t){return r=n[r],t=n[t],~r.m&&r.m==t.m&&~r.f&&r.f==t.f?"M"==r.s?"brother":"sister":void 0},i=function(r,t){return r=n[r],t=n[t],~r.m&&r.m==t.m||~r.f&&r.f==t.f?"M"==r.s?"half-brother":"half-sister":void 0},o=function(r){var n=("0"+r).slice(-2),t=n[0];return n=n[1],r+(1==t?"th":1==n?"st":2==n?"nd":3==n?"rd":"th")+" "},a=function(r){return 1==r?"once":2==r?"twice":3==r?"thrice":r+" times"},h=function(r,t){var e,f,i=[t],a=[n[t].m,n[t].f];for(e=0;e<n.length&&!~a.indexOf(r);e++){i=a.slice(),a=[];for(var h=0;h<i.length;h++)i[h]>=0&&a.push(n[i[h]].m,n[i[h]].f)}if(!(e>=n.length))return f="M"==n[r].s?"father":"mother",e>0&&(f="grand"+f),e>1&&(f="great-"+f),e>2&&(f=o(e-1)+f),f},u=function(r,t){var e=h(t,r);return e?e.slice(0,-6)+("M"==n[r].s?"son":"daughter"):void 0},s=function(r){for(var t=[],e=1;e<n.length;e++)f(r,e)&&e!=r&&t.push(e);return t},l=function(r){return r=r.slice(0,-6),""==r?r:"grand"==r?"great ":"great-grand"==r?"2nd great ":o(+r.split(" ")[0].slice(0,-2)+1)+"great "},v=function(r,t){for(var e,f=s(r),i=0;i<f.length&&!(e=h(f[i],t));i++);return e?l(e)+("M"==n[r].s?"uncle":"aunt"):void 0},c=function(r,t){var e=v(t,r);return e?(e.split(" ").slice(0,-1).join(" ")+("M"==n[r].s?" nephew":" niece")).trim():void 0},g=function(r,n){for(var t=0;t<r.length;t++)if(~n.indexOf(r[t]))return!0},m=function(r,t){r=n[r],t=n[t];for(var e=[[r.m,r.f]],f=[[t.m,t.f]],i=0;i<n.length;i++){for(var h=e[i],u=f[i],s=[],l=0;l<h.length;l++){var v=0,c=0;-1!=h[l]&&(v=n[h[l]].m,c=n[h[l]].f),v>0&&s.push(v),c>0&&s.push(c)}for(var m=[],l=0;l<u.length;l++){var v=0,c=0;-1!=u[l]&&(v=n[u[l]].m,c=n[u[l]].f),v>0&&m.push(v),c>0&&m.push(c)}if(!s.length&&!m.length)break;e.push(s),f.push(m)}for(var i=1;i<Math.min(e.length,f.length);i++){var h=e[i],u=f[i];if(g(h,u))return(i>1?o(i):"")+"cousin"}for(var i=1;i<e.length;i++)for(var h=e[i],l=1;l<f.length;l++){var u=f[l];if(g(h,u)){var p=Math.min(i,l);return(p>1?o(p):"")+"cousin, "+a(Math.abs(i-l))+" removed,"}}},e=prompt().split(" "),p=+e[0],d=+e[1],M=u(p,d)||h(p,d)||f(p,d)||i(p,d)||c(p,d)||v(p,d)||m(p,d);alert(n[p].n+" is "+(M?"the "+M+" of ":"not a blood relative to ")+n[d].n+".\n"

मुझे यकीन है कि इसे बहुत आगे बढ़ाया जा सकता है, मैंने जो कुछ भी किया था उसे एक मिनिफायर के माध्यम से एक ungolfed संस्करण में रखा गया था।

आप यहाँ ungolfed संस्करण को jsFiddle पर चला सकते हैं । यहाँ उदाहरण डेटा के लिए आउटपुट है:

1 2 Agatha is not a blood relative to Adam.
8 3 David is the son of Betty.
9 13 Emma is the mother of Grace.
4 5 Bertrand is the brother of Charlotte.
9 4 Emma is the niece of Bertrand.
5 8 Charlotte is the aunt of David.
16 7 Herbert is the grandson of Daisy.
1 9 Agatha is the grandmother of Emma.
12 5 Fred is the great nephew of Charlotte.
4 13 Bertrand is the great uncle of Grace.
16 3 Herbert is the great-grandson of Betty.
6 17 Carl is the great-grandfather of Jane.
19 1 Kate is the 3rd great-granddaughter of Agatha.
2 17 Adam is the 2nd great-grandfather of Jane.
20 4 Larry is the 3rd great nephew of Bertrand.
5 16 Charlotte is the 2nd great aunt of Herbert.
8 9 David is the cousin of Emma.
19 20 Kate is the 4th cousin of Larry.
16 9 Herbert is the cousin, twice removed, of Emma.
12 17 Fred is the 2nd cousin, once removed, of Jane.
21 20 Mary is the half-sister of Larry.

2

अजगर 3: 1183

def D(i):
 if i==a:return 0
 r=[D(c)for c in t[i][4]]
 if r:return min(x for x in r if x is not None)+1
def A(i):
 if i=="?":return None
 r=D(i)
 if r is not None:return 0,r
 m,f=map(A,t[i][:2])
 return(f[0]+1,f[1])if not m or(f and sum(f)<sum(m))else(m[0]+1,m[1])if f else None
def P(r):print("%s is %s of %s"%(t[a][3],r,t[b][3]))
O=lambda n:"%d%s "%(n,{2:"nd",3:"rd"}.get(n,"th"))
G=lambda n:(O(n-2)if n>3 else"")+("great-"if n>2 else"")
GG=lambda n:G(n)+("grand"if n>1 else"")
f,a,b=input().split()
t={}
for l in open(f):
 i,m,f,g,n=l.strip().split(maxsplit=4)
 t[i]=(m,f,g,n,[])
for i,(m,f,g,n,c)in t.items():
 if m in t:t[m][4].append(i)
 if f in t:t[f][4].append(i)
g=t[a][2]=="M"
r=A(b)
if r:
 u,d=r
 if u==d==1:P("the "+("half-"if t[s][0]!=t[e][0]or t[s][1]!=t[s][1]else"")+["sister","brother"][g])
 elif u==0:P("the "+GG(d)+["daughter","son"][g])
 elif d==0:P("the "+GG(u)+["mother","father"][g])
 elif u==1:P("the "+G(d)+["niece","nephew"][g])
 elif d==1:P("the "+G(u)+["aunt","uncle"][g])
 else:
  n,m=min(u,d)-1,abs(u-d);P("the "+(O(n)if n>1 else"")+"cousin"+(" %s removed"%{1:"once",2:"twice",3:"thrice"}.get(m,"%d times"%m)if m else""))
else:
 P("not a blood relative")

जिन लोगों के नाम और विवरण दर्ज किए जाने हैं, उनका नाम एकल लाइन पर मानक इनपुट से पढ़ा जाता है।

कोड का शीर्ष भाग फ़ंक्शन परिभाषा है। स्क्रिप्ट आधे-अधूरे तरीके से शुरू होती है, और पहले इनपुट को संसाधित करने (फ़ाइल को पार्स करने, फिर बच्चों को एक दूसरे पास में उनके माता-पिता को सौंपने) पर काम करती है।

डेटा सेट होने के बाद, हम कॉल करते हैं A पुनरावर्ती खोज को बंद करने के फ़ंक्शन को एक बार हैं। परिणाम रिश्ते को परिभाषित करता है।

बाकी कोड अंग्रेजी में उस रिश्ते का वर्णन करने के लिए समर्पित है। भाई-बहन और चचेरे भाई जटिल हैं (और लंबी लाइनों का उपयोग करते हैं), बाकी सभी बहुत सीधे हैं।

उदाहरण रन (दूसरी पंक्ति मेरा इनपुट है):

C:\>Python34\python.exe relations.py
relations.txt 20 4
Larry is the 3rd great-nephew of Bertrand

समारोह और चर नाम कुंजी:

  • f: परिवार का डेटा फ़ाइल नाम से पढ़ा जाता है।
  • a: जिस व्यक्ति का संबंध हम नामकरण कर रहे हैं, उसकी आईडी।
  • b: जिस व्यक्ति के संबंध के संबंध में आईडी परिभाषित की गई है।
  • t: परिवार का पेड़ ही, एक शब्द के रूप में एक आईडी से मां की आईडी, पिता की आईडी, लिंग, नाम और बच्चों की एक सूची का 5-tuple।
  • g: एक बूलियन मूल्य व्यक्ति के लिंग को दर्शाता है a। यह है Trueअगर वे एक पुरुष हैं।
  • u: से पीढ़ियों की संख्या bके आम पूर्वज के लिए aऔर b(या 0 अगर bहै aके पूर्वज)।
  • d: से पीढ़ियों की संख्या aके आम पूर्वज के लिए aऔर b(या 0 अगर aहै bके पूर्वज)।
  • D(i): व्यक्ति के iलिए व्यक्ति के वंश को फिर से खोजिए a। वापसी गहराई aपर पाया गया था, या कोई भी अगर यह नहीं पाया गया था।
  • A(i): पुनरावर्ती खोज iऔर iवंशज, लेकिन अगर इसकी पुनरावर्ती खोज iपूर्वजों (और उनके वंशजों) में भी नहीं मिली । एक 2-ट्यूपल लौटाता है, जिनका मान uऔर dऊपर वर्णित है। यदि कोई रिश्ता दोनों माता-पिता के माध्यम से पाया जाता है, तो सबसे छोटी संख्या वाले पीढ़ीगत कदम ( u+d) को प्राथमिकता दी जाती है। यदि व्यक्ति के aपास व्यक्ति के लिए कोई रक्त संबंध नहीं है i, तो A(i)रिटर्न करता है None
  • P(r): rव्यक्तियों के नामों के आधार पर प्रिंट रिजल्ट स्ट्रिंग ब्रैकेट aऔर b
  • O(n): दिए गए नंबर के लिए एक क्रमिक स्ट्रिंग लौटाएं n । केवल समर्थन करता है 1 < n < 21
  • G(n): के बराबर एक उपसर्ग स्ट्रिंग लौटें n-1 "Greats" (उदाहरण के "2nd great-"लिए n = 2`) के । N <= 1 के लिए एक रिक्त स्ट्रिंग लौटाएगा।
  • GG(n): "नथ महान-" और "भव्य" के साथ एक उपसर्ग स्ट्रिंग लौटाता है, जिसके लिए उपयुक्त है n पीढ़ियों के । N <= 1 के लिए एक रिक्त स्ट्रिंग लौटाएगा।

मैंने छोटे कोड के नाम पर कुछ शॉर्टकट लिए जो बड़े वंशावली पर बेहतर (या थोड़ा अधिक सही) प्रदर्शन के लिए संशोधित किए जा सकते थे। यह Aफ़ंक्शन बाल वृक्षों को गिराने से बचने का कोई प्रयास नहीं करता है जो पहले ही खोजे जा चुके हैं, जो इसे आवश्यक से धीमा बनाता है (हालांकि उचित आकार के परिवारों के लिए शायद अभी भी काफी तेजी से)। Oफ़ंक्शन ठीक ऑर्डिनल्स अधिक से अधिक 20 से संभाल नहीं करता है (यह के सभी प्राप्त करने के लिए एक सा मुश्किल है 11th, 21stऔर101st सही, लेकिन मेरे ड्राफ्ट संस्करणों में से एक में मैं 25 के बारे में अतिरिक्त बाइट्स में यह किया)। जब तक आप बहुत पुराने और प्रसिद्ध परिवारों (जैसे यूरोप के कुछ शाही परिवारों) के साथ काम कर रहे हैं, मुझे यकीन नहीं है कि मैं एक वंशावली की सटीकता पर भरोसा करूंगा जो कि वैसे भी वापस चली गई थी।

दूसरी ओर, मैंने कुछ स्थानों पर भी छोड़ दिया है जहाँ मैं कुछ बाइट्स काट सकता हूँ। उदाहरण के लिए, मैं GGएक एकल वर्ण नाम का नाम बदलकर 3 बाइट्स बचा सकता था , लेकिन great-grandमेरे नाम के अनुसार अधिक मूल्य के नाम को बंद करना।

मेरा मानना ​​है कि कोड में सभी श्वेत-स्थान की आवश्यकता है, लेकिन यह संभव है कि कुछ को छोड़ दिया जा सकता है और मैंने उन्हें याद किया है (मैं तर्क सूचियों में आवारा स्थान ढूंढता रहा क्योंकि मैं इस उत्तर को टाइप कर रहा था, लेकिन मुझे लगता है कि मैं ' अब उन सभी को मिल गया है)।

क्योंकि मेरे पुनरावर्ती मिलान के लिए एक अपेक्षाकृत सरल नियम की आवश्यकता होती है, जिसके लिए रिश्तों को पसंद करने के लिए यदि एक से अधिक है, तो मैं कुछ अस्पष्ट मामलों में बिल्कुल अनुरोधित परिणाम नहीं देता हूं, जिसमें अंतरजनपदीय अनाचार शामिल हैं। उदाहरण के लिए, यदि व्यक्ति aदोनों व्यक्ति bके चाचा और दादा हैं, तो मेरा कोड इस सवाल के बावजूद दादाजी के रिश्ते को पसंद करेगा कि चाचा रिश्ते में उच्चता होनी चाहिए।

यहाँ एक उदाहरण डाटासेट है जो समस्या को उजागर करता है:

1 ? ? F Alice
2 1 ? M Bob
3 1 2 F Claire
4 3 ? F Danielle

मुझे संदेह है कि ज्यादातर कार्यक्रमों के लिए, बॉब और क्लेयर के बीच या बॉब और डेनियल के बीच के रिश्ते परेशानी का कारण बनेंगे। वे या तो पिता / पुत्री के बजाय पहली जोड़ी को सौतेले भाई-बहन कहेंगे या वे बाद की जोड़ी को दादा / भतीजी के बजाय दादा / पोती के रूप में वर्णित करेंगे। मेरा कोड उत्तरार्द्ध करता है, और मुझे पहले जोड़े को भी गलत किए बिना अनुरोध किए गए परिणाम प्राप्त करने के लिए इसे बदलने का कोई उचित तरीका नहीं दिखता है।


0

एक परीक्षण सूट। इसे t / relation.t में बाँध लें और "prov" या "perl t / relation.t" चलाएं। यह वर्तमान में मानती है कि प्रोग्राम फ़ाइल "relation.rb" है।

यह सामुदायिक विकि है, इसलिए परीक्षणों को जोड़ने के लिए स्वतंत्र महसूस करें। यदि आप इसे बदलते हैं, तो मुझे लगता है कि एक टाइमस्टैम्प (या कुछ अन्य स्पष्ट ध्वज) क्रम में होगा। इच्छा सूची:

  1. एक "बुरा लड़का" परीक्षण जो संपूर्ण खोज रणनीतियों को दंडित करेगा
#
#       S. Leadley, Wed Aug 27 20:08:31 EDT 2014
use strict;
use warnings;
require File::Temp;
use File::Temp qw( tempfile tempdir );

use Test::More qw(no_plan);
# use Test::More tests => 38;


#       solution executable
my $solver='ruby relation.rb';


#       "happy" path
my $dir = tempdir( CLEANUP => 1 );
my ($fh, $filename) = tempfile( DIR => $dir );
my $testData = <<'END_TEST_DATA';
 1  ?  ? F Agatha
 2  ?  ? M Adam
 3  ?  ? F Betty
 4  1  2 M Bertrand
 5  1  2 F Charlotte
 6  ?  ? M Carl
 7  ?  ? F Daisy
 8  3  4 M David
 9  5  6 F Emma
10  ?  ? M Edward
11  ?  ? F Freya
12  7  8 M Fred
13  9 10 F Grace
14  ?  ? M Gerald
15  ?  ? F Hillary
16 11 12 M Herbert
17 13 14 F Jane
18  ?  ? M James
19 15 16 F Kate
20 17 18 M Larry
21  ? 18 F Mary
END_TEST_DATA
print $fh  $testData;
close($fh);

is( `$solver 1  2 $filename 2>&1`, "Agatha is not a blood relative to Adam.\n", 'OP example #1,  1  2');
is( `$solver 8 3 $filename 2>&1`, "David is the son of Betty.\n", 'OP example #2,  8  3');
is( `$solver 9 13 $filename 2>&1`, "Emma is the mother of Grace.\n", 'OP example #3,  9 13');
is( `$solver 4 5 $filename 2>&1`, "Bertrand is the brother of Charlotte.\n", 'OP example #4,  4  5');
is( `$solver 9 4 $filename 2>&1`, "Emma is the niece of Bertrand.\n", 'OP example #5,  9  5');
is( `$solver 5 8 $filename 2>&1`, "Charlotte is the aunt of David.\n", 'OP example #6,  5  8');
is( `$solver 16 7 $filename 2>&1`, "Herbert is the grandson of Daisy.\n", 'OP example #7, 16  7');
is( `$solver 1 9 $filename 2>&1`, "Agatha is the grandmother of Emma.\n", 'OP example #8,  1  9 (amended)');
is( `$solver 12 5 $filename 2>&1`, "Fred is the great-nephew of Charlotte.\n", 'OP example #9, 12  5');
is( `$solver 4 13 $filename 2>&1`, "Bertrand is the great-uncle of Grace.\n", 'OP example #10,  4 13');
is( `$solver 16 3 $filename 2>&1`, "Herbert is the great-grandson of Betty.\n", 'OP example #11, 16  3');
is( `$solver 6 17 $filename 2>&1`, "Carl is the great-grandfather of Jane.\n", 'OP example #12,  6 17');
is( `$solver 19 2 $filename 2>&1`, "Kate is the 3rd great-granddaughter of Adam.\n", 'OP example #13, 19  2 (amended)');
is( `$solver 1 17 $filename 2>&1`, "Agatha is the 2nd great-grandmother of Jane.\n", 'OP example #14,  1 17 (amended)');
is( `$solver 20 4 $filename 2>&1`, "Larry is the 3rd great-nephew of Bertrand.\n", 'OP example #15, 20  4');
is( `$solver 5 16 $filename 2>&1`, "Charlotte is the 2nd great-aunt of Herbert.\n", 'OP example #16,  5 16');
is( `$solver 8 9 $filename 2>&1`, "David is the cousin of Emma.\n", 'OP example #17,  8  9');
is( `$solver 19 20 $filename 2>&1`, "Kate is the 4th cousin of Larry.\n", 'OP example #18, 19 20');
is( `$solver 16 9 $filename 2>&1`, "Herbert is the cousin, twice removed, of Emma.\n", 'OP example #19, 16  9');
is( `$solver 12 17 $filename 2>&1`, "Fred is the 2nd cousin, once removed, of Jane.\n", 'OP example #20, 12 17');
is( `$solver 21 20 $filename 2>&1`, "Mary is the half-sister of Larry.\n", 'OP example #21, 21 20');


#       "sad" path
# none!


#       "bad" path
is( `$solver 1 32 $filename 2>&1`, "person with ID 32 does not exist\n", 'not required, not in the spec');


exit 0;
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.