Advertisement
Guest User

Complicated Hello World

a guest
Jul 26th, 2024
89
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 17.31 KB | Source Code | 0 0
  1. using System.Collections;
  2.  
  3. namespace HelloWorld;
  4.  
  5. public class StringTrieMap<T> : TrieMap<string, char, StringKeyHandler, T> { }
  6.  
  7. public class StringKeyHandler : ITrieKeyHandler<string, char>
  8. {
  9.     public static IEnumerable<char> Decompose(string key) => key;
  10.  
  11.     public static string CreateKeyObject(IEnumerable<char> elements) =>
  12.         string.Concat(elements);
  13. }
  14.  
  15. public class TrieMap<TKey, TKeyElement, TKeyHandler, TValue>
  16.     : ICollection<KeyValuePair<TKey, TValue>>,
  17.         IDictionary<TKey, TValue>,
  18.         IEnumerable<KeyValuePair<TKey, TValue>>,
  19.         IReadOnlyCollection<KeyValuePair<TKey, TValue>>,
  20.         IReadOnlyDictionary<TKey, TValue>
  21.     where TKeyElement : notnull
  22.     where TKeyHandler : ITrieKeyHandler<TKey, TKeyElement>
  23. {
  24.     public int Count => _root.Count;
  25.     public bool IsReadOnly => false;
  26.  
  27.     public TValue this[TKey key]
  28.     {
  29.         get
  30.         {
  31.             ArgumentNullException.ThrowIfNull(key, nameof(key));
  32.  
  33.             return _root.Get(TKeyHandler.Decompose(key));
  34.         }
  35.         set
  36.         {
  37.             ArgumentNullException.ThrowIfNull(key, nameof(key));
  38.  
  39.             _root.Replace(
  40.                 TKeyHandler.Decompose(key).GetEnumerator(),
  41.                 value,
  42.                 _comparer
  43.             );
  44.         }
  45.     }
  46.  
  47.     public ICollection<TKey> Keys
  48.     {
  49.         get
  50.         {
  51.             var keys = new List<TKey>();
  52.             var keyStack = new Stack<TKeyElement>();
  53.  
  54.             foreach (var _ in _root.EnumerateKeys(keyStack))
  55.             {
  56.                 keys.Add(TKeyHandler.CreateKeyObject(keyStack.Reverse()));
  57.             }
  58.  
  59.             return keys;
  60.         }
  61.     }
  62.  
  63.     IEnumerable<TKey> IReadOnlyDictionary<TKey, TValue>.Keys
  64.     {
  65.         get
  66.         {
  67.             var keyStack = new Stack<TKeyElement>();
  68.  
  69.             foreach (var _ in WrapEnumerable(_root.EnumerateKeys(keyStack)))
  70.             {
  71.                 yield return TKeyHandler.CreateKeyObject(keyStack.Reverse());
  72.             }
  73.         }
  74.     }
  75.  
  76.     public ICollection<TValue> Values =>
  77.         _root.EnumerateKeyValuePairs(new()).ToList();
  78.  
  79.     IEnumerable<TValue> IReadOnlyDictionary<TKey, TValue>.Values =>
  80.         WrapEnumerable(_root.EnumerateKeyValuePairs(new()));
  81.  
  82.     private TrieNode<
  83.         TKeyElement,
  84.         TValue,
  85.         TValue,
  86.         TrieMapStorageAccessor<TValue>
  87.     > _root;
  88.     private IComparer<TKeyElement> _comparer;
  89.     private int _version = 0;
  90.  
  91.     public TrieMap(IComparer<TKeyElement>? comparer = null)
  92.     {
  93.         _comparer = comparer ?? Comparer<TKeyElement>.Default;
  94.         _root = new(_comparer);
  95.     }
  96.  
  97.     public TrieMap(
  98.         IEnumerable<KeyValuePair<TKey, TValue>> collection,
  99.         IComparer<TKeyElement>? comparer = null
  100.     )
  101.         : this(comparer)
  102.     {
  103.         foreach (var item in collection)
  104.         {
  105.             Add(item.Key, item.Value);
  106.         }
  107.     }
  108.  
  109.     public void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
  110.     {
  111.         ArgumentNullException.ThrowIfNull(array, nameof(array));
  112.         ArgumentOutOfRangeException.ThrowIfNegative(
  113.             arrayIndex,
  114.             nameof(arrayIndex)
  115.         );
  116.  
  117.         if (array.Length - arrayIndex < Count)
  118.         {
  119.             throw new ArgumentException("Not enough room to copy to.");
  120.         }
  121.  
  122.         var i = arrayIndex;
  123.  
  124.         foreach (var item in this)
  125.         {
  126.             array[i++] = item;
  127.         }
  128.     }
  129.  
  130.     public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
  131.     {
  132.         var keyStack = new Stack<TKeyElement>();
  133.  
  134.         foreach (
  135.             var value in WrapEnumerable(_root.EnumerateKeyValuePairs(keyStack))
  136.         )
  137.         {
  138.             yield return new KeyValuePair<TKey, TValue>(
  139.                 TKeyHandler.CreateKeyObject(keyStack.Reverse()),
  140.                 value
  141.             );
  142.         }
  143.     }
  144.  
  145.     IEnumerator IEnumerable.GetEnumerator() =>
  146.         ((IEnumerable<KeyValuePair<TKey, TValue>>)this).GetEnumerator();
  147.  
  148.     public bool TryGetValue(TKey key, out TValue value)
  149.     {
  150.         ArgumentNullException.ThrowIfNull(key, nameof(key));
  151.  
  152.         return _root.TryGetValue(TKeyHandler.Decompose(key), out value);
  153.     }
  154.  
  155.     public bool Contains(KeyValuePair<TKey, TValue> item)
  156.     {
  157.         ArgumentNullException.ThrowIfNull(item, nameof(item));
  158.         ArgumentNullException.ThrowIfNull(item.Key, nameof(item.Key));
  159.  
  160.         return _root.Contains(TKeyHandler.Decompose(item.Key), item.Value);
  161.     }
  162.  
  163.     public bool ContainsKey(TKey key)
  164.     {
  165.         ArgumentNullException.ThrowIfNull(key, nameof(key));
  166.  
  167.         return _root.ContainsKey(TKeyHandler.Decompose(key));
  168.     }
  169.  
  170.     public void Add(KeyValuePair<TKey, TValue> item)
  171.     {
  172.         ArgumentNullException.ThrowIfNull(item, nameof(item));
  173.  
  174.         Add(item.Key, item.Value);
  175.     }
  176.  
  177.     public void Add(TKey key, TValue value)
  178.     {
  179.         ArgumentNullException.ThrowIfNull(key, nameof(key));
  180.  
  181.         var oldCount = Count;
  182.         _root.Add(
  183.             TKeyHandler.Decompose(key).GetEnumerator(),
  184.             value,
  185.             _comparer
  186.         );
  187.         UpdateVersion(oldCount);
  188.     }
  189.  
  190.     public bool Remove(KeyValuePair<TKey, TValue> item)
  191.     {
  192.         ArgumentNullException.ThrowIfNull(item, nameof(item));
  193.         ArgumentNullException.ThrowIfNull(item.Key, nameof(item.Key));
  194.  
  195.         var oldCount = Count;
  196.         _root.Remove(
  197.             TKeyHandler.Decompose(item.Key).GetEnumerator(),
  198.             item.Value
  199.         );
  200.         return UpdateVersion(oldCount);
  201.     }
  202.  
  203.     public bool Remove(TKey key)
  204.     {
  205.         ArgumentNullException.ThrowIfNull(key, nameof(key));
  206.  
  207.         var oldCount = Count;
  208.         _root.RemoveKey(TKeyHandler.Decompose(key).GetEnumerator());
  209.         return UpdateVersion(oldCount);
  210.     }
  211.  
  212.     public void Clear()
  213.     {
  214.         var oldCount = Count;
  215.         _root.Clear();
  216.         UpdateVersion(oldCount);
  217.     }
  218.  
  219.     private IEnumerable<T> WrapEnumerable<T>(IEnumerable<T> enumerable)
  220.     {
  221.         var initialVersion = _version;
  222.  
  223.         foreach (var value in enumerable)
  224.         {
  225.             yield return _version == initialVersion
  226.                 ? value
  227.                 : throw new InvalidOperationException(
  228.                     "Collection was modified after the enumerator was instantiated."
  229.                 );
  230.         }
  231.     }
  232.  
  233.     private bool UpdateVersion(int oldCount)
  234.     {
  235.         if (_root.Count != oldCount)
  236.         {
  237.             ++_version;
  238.             return true;
  239.         }
  240.         else
  241.         {
  242.             return false;
  243.         }
  244.     }
  245. }
  246.  
  247. internal class TrieMapStorageAccessor<TValue>
  248.     : ITrieNodeStorageAccessor<TValue, TValue>
  249. {
  250.     public static void Add(
  251.         TValue value,
  252.         ref TValue? storage,
  253.         ref bool hasStorage,
  254.         ref int count
  255.     )
  256.     {
  257.         if (hasStorage)
  258.         {
  259.             throw new ArgumentException(
  260.                 "An element with the given key already exists."
  261.             );
  262.         }
  263.  
  264.         storage = value;
  265.         hasStorage = true;
  266.         ++count;
  267.     }
  268.  
  269.     public static void Remove(
  270.         TValue value,
  271.         ref TValue? storage,
  272.         ref bool hasStorage,
  273.         ref int count
  274.     )
  275.     {
  276.         if (!hasStorage || StorageEquals(storage!, value))
  277.         {
  278.             return;
  279.         }
  280.  
  281.         hasStorage = false;
  282.         --count;
  283.         storage = default;
  284.     }
  285.  
  286.     public static bool Contains(TValue storage, TValue value) =>
  287.         Equals(storage, value);
  288.  
  289.     public static IEnumerable<TValue> Enumerate(TValue storage)
  290.     {
  291.         yield return storage;
  292.     }
  293.  
  294.     public static TValue Clone(TValue storage) => storage;
  295.  
  296.     public static bool StorageEquals(TValue a, TValue b) => Equals(a, b);
  297.  
  298.     public static int Count(TValue storage) => 1;
  299. }
  300.  
  301. internal class TrieNode<TKeyElement, TValue, TStore, TStorageAccessor>
  302.     where TKeyElement : notnull
  303.     where TStorageAccessor : ITrieNodeStorageAccessor<TValue, TStore>
  304. {
  305.     public int Count => _count;
  306.  
  307.     private TStore? _storage;
  308.     private bool _hasStorage;
  309.     private int _count;
  310.     private SortedDictionary<
  311.         TKeyElement,
  312.         TrieNode<TKeyElement, TValue, TStore, TStorageAccessor>
  313.     > _children;
  314.  
  315.     public TrieNode(IComparer<TKeyElement> comparer)
  316.     {
  317.         _storage = default;
  318.         _hasStorage = false;
  319.         _count = 0;
  320.         _children = new(comparer);
  321.     }
  322.  
  323.     public TrieNode(
  324.         TrieNode<TKeyElement, TValue, TStore, TStorageAccessor> other,
  325.         IComparer<TKeyElement> comparer
  326.     )
  327.         : this(comparer)
  328.     {
  329.         if (other._hasStorage)
  330.         {
  331.             _storage = TStorageAccessor.Clone(other._storage!);
  332.             _hasStorage = true;
  333.         }
  334.  
  335.         foreach (var (keyElement, child) in other._children)
  336.         {
  337.             _children[keyElement] = new TrieNode<
  338.                 TKeyElement,
  339.                 TValue,
  340.                 TStore,
  341.                 TStorageAccessor
  342.             >(child, comparer);
  343.         }
  344.  
  345.         _count = other.Count;
  346.     }
  347.  
  348.     public bool Contains(IEnumerable<TKeyElement> key, TValue value)
  349.     {
  350.         var node = this;
  351.  
  352.         foreach (var keyElement in key)
  353.         {
  354.             if (!node._children.TryGetValue(keyElement, out node))
  355.             {
  356.                 return false;
  357.             }
  358.         }
  359.  
  360.         return node._hasStorage
  361.             && TStorageAccessor.Contains(node._storage!, value);
  362.     }
  363.  
  364.     public bool ContainsKey(IEnumerable<TKeyElement> key)
  365.     {
  366.         var node = this;
  367.  
  368.         foreach (var keyElement in key)
  369.         {
  370.             if (!node._children.TryGetValue(keyElement, out node))
  371.             {
  372.                 return false;
  373.             }
  374.         }
  375.  
  376.         return node._hasStorage;
  377.     }
  378.  
  379.     // This method is currently unused, but I might need it later
  380.     public IEnumerable<TValue> GetAll(IEnumerable<TKeyElement> key)
  381.     {
  382.         var node = this;
  383.  
  384.         foreach (var keyElement in key)
  385.         {
  386.             if (!node._children.TryGetValue(keyElement, out node))
  387.             {
  388.                 yield break;
  389.             }
  390.         }
  391.  
  392.         if (!node._hasStorage)
  393.         {
  394.             yield break;
  395.         }
  396.  
  397.         foreach (var value in TStorageAccessor.Enumerate(node._storage!))
  398.         {
  399.             yield return value;
  400.         }
  401.     }
  402.  
  403.     public IEnumerable<Nothing> EnumerateKeys(Stack<TKeyElement> prefix)
  404.     {
  405.         if (_hasStorage)
  406.         {
  407.             yield return default;
  408.         }
  409.  
  410.         foreach (var (keyElement, child) in _children)
  411.         {
  412.             prefix.Push(keyElement);
  413.  
  414.             foreach (var value in child.EnumerateKeys(prefix))
  415.             {
  416.                 yield return value;
  417.             }
  418.  
  419.             prefix.Pop();
  420.         }
  421.     }
  422.  
  423.     public IEnumerable<TValue> EnumerateKeyValuePairs(
  424.         Stack<TKeyElement> prefix
  425.     )
  426.     {
  427.         if (_hasStorage)
  428.         {
  429.             foreach (var value in TStorageAccessor.Enumerate(_storage!))
  430.             {
  431.                 yield return value;
  432.             }
  433.         }
  434.  
  435.         foreach (var (keyElement, child) in _children)
  436.         {
  437.             prefix.Push(keyElement);
  438.  
  439.             foreach (var value in child.EnumerateKeyValuePairs(prefix))
  440.             {
  441.                 yield return value;
  442.             }
  443.  
  444.             prefix.Pop();
  445.         }
  446.     }
  447.  
  448.     public TStore Get(IEnumerable<TKeyElement> key)
  449.     {
  450.         var node = this;
  451.  
  452.         foreach (var keyElement in key)
  453.         {
  454.             if (!node._children.TryGetValue(keyElement, out node))
  455.             {
  456.                 throw new KeyNotFoundException(
  457.                     "The given key was not present."
  458.                 );
  459.             }
  460.         }
  461.  
  462.         if (!node._hasStorage)
  463.         {
  464.             throw new KeyNotFoundException("The given key was not present.");
  465.         }
  466.  
  467.         return node._storage!;
  468.     }
  469.  
  470.     public bool TryGetValue(IEnumerable<TKeyElement> key, out TStore value)
  471.     {
  472.         var node = this;
  473.  
  474.         foreach (var keyElement in key)
  475.         {
  476.             if (!node._children.TryGetValue(keyElement, out node))
  477.             {
  478.                 value = default!;
  479.                 return false;
  480.             }
  481.         }
  482.  
  483.         if (!node._hasStorage)
  484.         {
  485.             throw new KeyNotFoundException("The given key was not present.");
  486.         }
  487.  
  488.         value = node._storage!;
  489.         return true;
  490.     }
  491.  
  492.     public void Clear()
  493.     {
  494.         _hasStorage = false;
  495.         _count = 0;
  496.         _storage = default;
  497.         _children.Clear();
  498.     }
  499.  
  500.     public void Add(
  501.         IEnumerator<TKeyElement> key,
  502.         TValue value,
  503.         IComparer<TKeyElement> comparer
  504.     )
  505.     {
  506.         if (!key.MoveNext())
  507.         {
  508.             TStorageAccessor.Add(
  509.                 value,
  510.                 ref _storage,
  511.                 ref _hasStorage,
  512.                 ref _count
  513.             );
  514.             return;
  515.         }
  516.  
  517.         var keyElement = key.Current;
  518.  
  519.         if (!_children.TryGetValue(keyElement, out var child))
  520.         {
  521.             child = new TrieNode<
  522.                 TKeyElement,
  523.                 TValue,
  524.                 TStore,
  525.                 TStorageAccessor
  526.             >(comparer);
  527.             _children[keyElement] = child;
  528.         }
  529.  
  530.         var oldCount = child._count;
  531.         child.Add(key, value, comparer);
  532.         _count += child._count - oldCount;
  533.     }
  534.  
  535.     public void Replace(
  536.         IEnumerator<TKeyElement> key,
  537.         TStore storage,
  538.         IComparer<TKeyElement> comparer
  539.     )
  540.     {
  541.         if (!key.MoveNext())
  542.         {
  543.             if (_hasStorage)
  544.             {
  545.                 _count -= TStorageAccessor.Count(_storage!);
  546.                 _storage = storage;
  547.             }
  548.             else
  549.             {
  550.                 _storage = storage;
  551.                 _hasStorage = true;
  552.             }
  553.  
  554.             _count += TStorageAccessor.Count(_storage);
  555.  
  556.             return;
  557.         }
  558.  
  559.         var keyElement = key.Current;
  560.  
  561.         if (!_children.TryGetValue(keyElement, out var child))
  562.         {
  563.             child = new TrieNode<
  564.                 TKeyElement,
  565.                 TValue,
  566.                 TStore,
  567.                 TStorageAccessor
  568.             >(comparer);
  569.             _children[keyElement] = child;
  570.         }
  571.  
  572.         var oldCount = child._count;
  573.         child.Replace(key, storage, comparer);
  574.         _count += child._count - oldCount;
  575.     }
  576.  
  577.     public void Remove(IEnumerator<TKeyElement> key, TValue value)
  578.     {
  579.         if (!key.MoveNext())
  580.         {
  581.             TStorageAccessor.Remove(
  582.                 value,
  583.                 ref _storage,
  584.                 ref _hasStorage,
  585.                 ref _count
  586.             );
  587.  
  588.             return;
  589.         }
  590.  
  591.         var keyElement = key.Current;
  592.  
  593.         if (!_children.TryGetValue(keyElement, out var child))
  594.         {
  595.             return;
  596.         }
  597.  
  598.         var oldCount = child._count;
  599.         child.Remove(key, value);
  600.         _count += child._count - oldCount;
  601.  
  602.         if (child._count == 0)
  603.         {
  604.             _children.Remove(keyElement);
  605.         }
  606.     }
  607.  
  608.     public void RemoveKey(IEnumerator<TKeyElement> key)
  609.     {
  610.         if (!key.MoveNext())
  611.         {
  612.             if (_hasStorage)
  613.             {
  614.                 _hasStorage = false;
  615.                 _count -= TStorageAccessor.Count(_storage!);
  616.                 _storage = default;
  617.             }
  618.  
  619.             return;
  620.         }
  621.  
  622.         var keyElement = key.Current;
  623.  
  624.         if (!_children.TryGetValue(keyElement, out var child))
  625.         {
  626.             return;
  627.         }
  628.  
  629.         var oldCount = child._count;
  630.         child.RemoveKey(key);
  631.         _count += child._count - oldCount;
  632.  
  633.         if (child._count == 0)
  634.         {
  635.             _children.Remove(keyElement);
  636.         }
  637.     }
  638. }
  639.  
  640. public interface ITrieKeyHandler<TKey, TKeyElement>
  641. {
  642.     static abstract IEnumerable<TKeyElement> Decompose(TKey key);
  643.  
  644.     static abstract TKey CreateKeyObject(IEnumerable<TKeyElement> elements);
  645. }
  646.  
  647. internal interface ITrieNodeStorageAccessor<TValue, TStore>
  648. {
  649.     static abstract void Add(
  650.         TValue value,
  651.         ref TStore? storage,
  652.         ref bool hasStorage,
  653.         ref int count
  654.     );
  655.  
  656.     static abstract void Remove(
  657.         TValue value,
  658.         ref TStore? storage,
  659.         ref bool hasStorage,
  660.         ref int count
  661.     );
  662.  
  663.     static abstract bool Contains(TStore storage, TValue value);
  664.  
  665.     static abstract IEnumerable<TValue> Enumerate(TStore storage);
  666.  
  667.     static abstract TStore Clone(TStore storage);
  668.  
  669.     static abstract bool StorageEquals(TStore a, TStore b);
  670.  
  671.     static abstract int Count(TStore storage);
  672. }
  673.  
  674. internal struct Nothing { }
  675.  
  676. internal class Program
  677. {
  678.     private static void Main()
  679.     {
  680.         var wordsWithPunctuation =
  681.             (IReadOnlyDictionary<string, char?>)
  682.                 new StringTrieMap<char?>()
  683.                 {
  684.                     { "Hello", ',' },
  685.                     { "World", null }
  686.                 };
  687.  
  688.         // IMPORTANT: Only works because hello world is in alphabetic order
  689.         Console.WriteLine(
  690.             string.Join(
  691.                 ' ',
  692.                 wordsWithPunctuation.Select(item =>
  693.                     item.Value is null ? item.Key : $"{item.Key}{item.Value}"
  694.                 )
  695.             )
  696.         );
  697.     }
  698. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement