Advertisement
Guest User

Untitled

a guest
Jan 20th, 2020
97
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 15.42 KB | None | 0 0
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using LINQ.Lessons.Contract;
  5. using MoreLinq;
  6.  
  7. namespace LINQ.Lessons
  8. {
  9.     public static class FamilyTreeExtensions
  10.     {
  11.         public static Person GetMotherOrNull(this Person person, ICollection<Person> persons)
  12.         {
  13.             if (person == null)
  14.                 return null;
  15.  
  16.             return persons.FirstOrDefault(x => x.Name.Equals(person.MotherName, StringComparison.InvariantCultureIgnoreCase));
  17.         }
  18.  
  19.         public static Person GetFatherOrNull(this Person person, ICollection<Person> persons)
  20.         {
  21.             if (person == null)
  22.                 return null;
  23.  
  24.             return persons.FirstOrDefault(x => x.Name.Equals(person.FatherName, StringComparison.InvariantCultureIgnoreCase));
  25.         }
  26.  
  27.         public static IEnumerable<Person> GetGrandMothersOrNull(this Person person, ICollection<Person> persons)
  28.         {
  29.             yield return person.GetMotherOrNull(persons)
  30.                                .GetMotherOrNull(persons);
  31.  
  32.             yield return person.GetFatherOrNull(persons)
  33.                                .GetMotherOrNull(persons);
  34.         }
  35.  
  36.         public static IEnumerable<Person> GetGrandFatherOrNull(this Person person, ICollection<Person> persons)
  37.         {
  38.             yield return person.GetFatherOrNull(persons)
  39.                                .GetFatherOrNull(persons);
  40.  
  41.             yield return person.GetMotherOrNull(persons)
  42.                                .GetFatherOrNull(persons);
  43.         }
  44.  
  45.         public static IEnumerable<Person> GetChildrenOrNull(this Person person, ICollection<Person> persons)
  46.         {
  47.             if (person == null)
  48.                 return null;
  49.  
  50.             var filterFunction = person.Sex == Sex.Male
  51.                                      ? new Func<Person, bool>(p => p.FatherName?.Equals(person.Name) == true)
  52.                                      : p => p.MotherName?.Equals(person.Name) == true;
  53.  
  54.             return persons.Where(filterFunction);
  55.         }
  56.  
  57.         public static IEnumerable<Person> GetBloodBrothersOrNull(this Person person, ICollection<Person> persons)
  58.         {
  59.             if (person == null)
  60.                 return null;
  61.  
  62.             var parent = person.GetMotherOrNull(persons) ?? person.GetFatherOrNull(persons);
  63.  
  64.             return parent
  65.                    .GetChildrenOrNull(persons)
  66.                    .Where(p => string.Equals(p.FatherName, person.FatherName)
  67.                                && string.Equals(p.MotherName, person.MotherName)
  68.                                && p.Sex == Sex.Male
  69.                                && !string.Equals(p.Name, person.Name));
  70.         }
  71.  
  72.         public static IEnumerable<Person> GetBloodSistersOrNull(this Person person, ICollection<Person> persons)
  73.         {
  74.             if (person == null)
  75.                 return null;
  76.  
  77.             var parent = person.GetMotherOrNull(persons) ?? person.GetFatherOrNull(persons);
  78.  
  79.             return parent
  80.                    .GetChildrenOrNull(persons)
  81.                    .Where(p => string.Equals(p.FatherName, person.FatherName)
  82.                                && string.Equals(p.MotherName, person.MotherName)
  83.                                && p.Sex == Sex.Female
  84.                                && !string.Equals(p.Name, person.Name));
  85.         }
  86.  
  87.         public static IEnumerable<Person> GetBrothersByFatherLoversOrNull(this Person person, ICollection<Person> persons)
  88.         {
  89.             if (person == null)
  90.                 return null;
  91.  
  92.             return person.GetFatherOrNull(persons)
  93.                          .GetChildrenOrNull(persons)
  94.                          .Where(p => !string.Equals(p.MotherName, person.MotherName) && p.Sex == Sex.Male && !string.Equals(p.Name, person.Name));
  95.         }
  96.  
  97.         public static IEnumerable<Person> GetBrothersByMotherLoversOrNull(this Person person, ICollection<Person> persons)
  98.         {
  99.             if (person == null)
  100.                 return null;
  101.  
  102.             return person.GetFatherOrNull(persons)
  103.                          .GetChildrenOrNull(persons)
  104.                          .Where(p => !string.Equals(p.FatherName, person.FatherName) && p.Sex == Sex.Male && !string.Equals(p.Name, person.Name));
  105.         }
  106.  
  107.         public static IEnumerable<Person> GetAncestorsOrNull(this Person person, ICollection<Person> persons)
  108.         {
  109.             var mother = person.GetMotherOrNull(persons);
  110.             if (mother != null)
  111.             {
  112.                 yield return mother;
  113.                 foreach (var ancestor in mother.GetAncestorsOrNull(persons))
  114.                 {
  115.                     yield return ancestor;
  116.                 }
  117.             }
  118.  
  119.             var father = person.GetFatherOrNull(persons);
  120.             if (father != null)
  121.             {
  122.                 yield return father;
  123.                 foreach (var ancestor in father.GetAncestorsOrNull(persons))
  124.                 {
  125.                     yield return ancestor;
  126.                 }
  127.             }
  128.         }
  129.  
  130.         public static IEnumerable<Person> GetDescendantsOrNull(this Person person, ICollection<Person> persons)
  131.         {
  132.             if (person == null)
  133.                 yield return null;
  134.  
  135.             var children = person.GetChildrenOrNull(persons);
  136.  
  137.             if (children != null)
  138.             {
  139.                 foreach (var child in children)
  140.                 {
  141.                     yield return child;
  142.  
  143.                     foreach (var descendant in child.GetDescendantsOrNull(persons))
  144.                     {
  145.                         yield return descendant;
  146.                     }
  147.                 }
  148.             }
  149.         }
  150.  
  151.         public static IEnumerable<Person> GetRelativesOrNull(this Person person, ICollection<Person> persons)
  152.         {
  153.             var ancestorsOrNull = person.GetAncestorsOrNull(persons);
  154.            
  155.             if (ancestorsOrNull == null)
  156.                 return null;
  157.  
  158.             var ancestorsAndPerson = ancestorsOrNull
  159.                                      .Concat(new[] {person})
  160.                                      .ToList();
  161.  
  162.             return ancestorsAndPerson
  163.                    .Select(p => p.GetDescendantsOrNull(persons))
  164.                    .SelectMany(x => x)
  165.                    .Concat(ancestorsAndPerson)
  166.                    .Except(new[] {person})
  167.                    .Distinct();
  168.         }
  169.  
  170.         //todo поправить
  171.         public static IEnumerable<Person> GetRelatives(this Person person, ICollection<Person> persons)
  172.         {
  173.             var ancestors = person?.GetAncestorsOrNull(persons);
  174.             if (ancestors == null)
  175.                 return null;
  176.  
  177.             return ancestors.SelectMany(x => x.GetDescendantsOrNull(persons))
  178.                             .Distinct()
  179.                             .Except(new[] {person});
  180.         }
  181.  
  182.         public static IEnumerable<Person> GetTree(this Person person,
  183.                                                   ICollection<Person> persons,
  184.                                                   HashSet<Person> visited = null)
  185.         {
  186.             if (visited == null)
  187.                 visited = new HashSet<Person>();
  188.            
  189.             if (person == null || visited.Contains(person))
  190.                 yield break;
  191.            
  192.             yield return person;
  193.            
  194.             visited.Add(person);
  195.  
  196.             var childrenOrNull = person.GetChildrenOrNull(persons);
  197.             if (childrenOrNull == null)
  198.                 yield break;
  199.             foreach (var child in childrenOrNull)
  200.             {
  201.                 foreach (var result in child.GetTree(persons, visited))
  202.                     yield return result;
  203.             }
  204.  
  205.             var fatherOrNull = person.GetFatherOrNull(persons);
  206.             if (fatherOrNull == null)
  207.                 yield break;
  208.             foreach (var result in fatherOrNull.GetTree(persons, visited))
  209.                 yield return result;
  210.  
  211.             var motherOrNull = person.GetMotherOrNull(persons);
  212.             if (motherOrNull == null)
  213.                 yield break;
  214.             foreach (var result in motherOrNull.GetTree(persons, visited))
  215.                 yield return result;
  216.         }
  217.  
  218.         public static IEnumerable<PersonWithLvl> GetTreeWithLevels(this Person person,
  219.                                                                    ICollection<Person> persons,
  220.                                                                    HashSet<Person> visited = null,
  221.                                                                    int currentLvl = 0)
  222.         {
  223.             visited = visited ?? new HashSet<Person>();
  224.  
  225.             if (person == null || visited.Contains(person))
  226.                 yield break;
  227.  
  228.             yield return new PersonWithLvl(person, currentLvl);
  229.  
  230.             visited.Add(person);
  231.  
  232.             var childrenOrNull = person.GetChildrenOrNull(persons);
  233.             foreach (var child in childrenOrNull)
  234.             {
  235.                 var lvlUp = currentLvl + 1;
  236.                 var childResults = child.GetTreeWithLevels(persons, visited, currentLvl: lvlUp);
  237.                 foreach (var result in childResults)
  238.                     yield return result;
  239.             }
  240.  
  241.             var fatherOrNull = person.GetFatherOrNull(persons);
  242.             var lvlDown = currentLvl - 1;
  243.             var fatherResults = fatherOrNull.GetTreeWithLevels(persons, visited, currentLvl: lvlDown);
  244.             foreach (var result in fatherResults)
  245.                 yield return result;
  246.  
  247.             var motherOrNull = person.GetMotherOrNull(persons);
  248.             var motherResults = motherOrNull.GetTreeWithLevels(persons, visited, currentLvl: lvlDown);
  249.             foreach (var result in motherResults)
  250.                 yield return result;
  251.         }
  252.  
  253.         public static IEnumerable<IEnumerable<Person>> GetTrees(ICollection<Person> persons)
  254.         {
  255.             var visited = new HashSet<Person>();
  256.             while (visited.Count != persons.Count)
  257.             {
  258.                 var firstNotVisited = persons.FirstOrDefault(p => !visited.Contains(p));
  259.                 var tree = firstNotVisited.GetTree(persons).ToList();
  260.                 yield return tree;
  261.                 tree.ForEach(x => visited.Add(x));
  262.             }
  263.         }
  264.  
  265.         public static IEnumerable<IEnumerable<PersonWithLvl>> GetTreesWithLvl(this ICollection<Person> persons)
  266.         {
  267.             var visited = new HashSet<Person>();
  268.             while (visited.Count != persons.Count)
  269.             {
  270.                 var firstNotVisited = persons.FirstOrDefault(p => !visited.Contains(p));
  271.                 var tree = firstNotVisited.GetTreeWithLevels(persons).ToList();
  272.                 yield return tree;
  273.                 tree.ForEach(x => visited.Add(x.Person));
  274.             }
  275.         }
  276.  
  277.         public static bool IsInOneGenerationWith(this Person person1, Person person2, ICollection<Person> persons)
  278.         {
  279.             var person2WithLvlOrNull = person1.GetTreeWithLevels(persons)
  280.                                               .FirstOrDefault(x => x.Equals(person2));
  281.             if (person2WithLvlOrNull == null || person2WithLvlOrNull.Level == 0)
  282.                 return false;
  283.             return true;
  284.         }
  285.  
  286.         public static Person GetNearestCommonAncestorOrNull(this Person person1, Person person2, ICollection<Person> persons)
  287.         {
  288.             var ancestorsForPerson1 = person1.GetAncestorsOrNull(persons);
  289.             if (ancestorsForPerson1 == null)
  290.                 return null;
  291.            
  292.             var ancestorsForPerson2 = person2.GetAncestorsOrNull(persons);
  293.             if (ancestorsForPerson2 == null)
  294.                 return null;
  295.  
  296.             var ancestorsForPerson1Set = new HashSet<Person>(ancestorsForPerson1);
  297.  
  298.             var treeWithLevels = person2.GetTreeWithLevels(persons);
  299.             var ancestorsIntersection = treeWithLevels?
  300.                                         .Where(x => ancestorsForPerson1Set.Contains(x.Person))
  301.                                         .ToList();
  302.             if (ancestorsIntersection == null || ancestorsIntersection.Count == 0)
  303.                 return null;
  304.  
  305.             return ancestorsIntersection.OrderBy(x => x.Level)
  306.                                         .First()
  307.                                         .Person;
  308.         }
  309.  
  310.         public static void PrintTrees(this Person[] persons)
  311.         {
  312.             foreach (var treeWithLvl in persons.GetTreesWithLvl())
  313.             {
  314.                 PrintTree(treeWithLvl);
  315.             }
  316.         }
  317.  
  318.         private static void PrintTree(this IEnumerable<PersonWithLvl> persons)
  319.         {
  320.             var personWithLvls = persons as PersonWithLvl[] ?? persons.ToArray();
  321.             var sortedPersons = personWithLvls.OrderBy(x => x.Level)
  322.                                               .ToArray();
  323.  
  324.             var lvls = personWithLvls.Select(x => x.Level)
  325.                                      .OrderBy(x => x)
  326.                                      .Distinct()
  327.                                      .ToArray();
  328.  
  329.             var groupByLvl = personWithLvls.ToLookup(x => x.Level);
  330.  
  331.             if (sortedPersons.Length == 0)
  332.                 return;
  333.  
  334.             var minTreeLvl = Math.Abs(lvls[0]);
  335.  
  336.             foreach (var lvl in lvls)
  337.             {
  338.                 var generation = groupByLvl[lvl];
  339.                 var tabsCount = lvl + minTreeLvl;
  340.                 var tabs = new string('\t', tabsCount);
  341.                 Console.WriteLine($"Gen {lvl}->{tabs}{string.Join("|", generation.Select(x => x.Person.Name))}");
  342.             }
  343.         }
  344.  
  345.         public static IEnumerable<Person> FindBestPath(this Person fromPerson,
  346.                                                        Person toPerson,
  347.                                                        ICollection<Person> persons)
  348.         {
  349.  
  350.             var path = new Dictionary<Person, Person>();
  351.             var queue = new Queue<Person>();
  352.             queue.Enqueue(toPerson);
  353.             path[toPerson] = null;
  354.             while (queue.Count != 0)
  355.             {
  356.                 var person = queue.Dequeue();
  357.                 var nextPersons = person.GetChildrenOrNull(persons)
  358.                                         .Concat(new[] {person.GetFatherOrNull(persons), person.GetMotherOrNull(persons)})
  359.                                         .Where(p => p != null && !path.ContainsKey(p));
  360.  
  361.                 foreach (var nextPerson in nextPersons)
  362.                 {
  363.                     queue.Enqueue(nextPerson);
  364.                     path[nextPerson] = person;
  365.                 }
  366.                 if (path.ContainsKey(fromPerson))
  367.                     break;
  368.             }
  369.            
  370.             yield return fromPerson;
  371.             while (fromPerson != null && path[fromPerson] != null)
  372.                 yield return fromPerson = path[fromPerson];
  373.         }
  374.  
  375.         //todo свойствО (ударение на последнюю О). цепочка общих родственников
  376.         //todo находятся ли два человека в одном поколении.
  377.         //todo 2 человека, найти самого ближайшего общего предка
  378.  
  379.  
  380.         //todo вывод деревьев по поколениям
  381.         //todo 2 человека, найти самого ближайшего общего предка
  382.         //todo для двух свояков найти самую короткую цепочку родственников
  383.     }
  384.  
  385. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement