0% found this document useful (0 votes)
17 views

Dcexercises

The document contains solutions to several programming exercises involving dictionaries, hash tables, and sets. It implements dictionaries to count the occurrences of integers in an array and words in a text file. It also implements a hash table that stores triples using keys and allows searching by key pairs. Finally, it implements a set using a hash table to store elements and supports standard set operations like add, find, remove, union, and intersect.

Uploaded by

bekaelsa172
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
17 views

Dcexercises

The document contains solutions to several programming exercises involving dictionaries, hash tables, and sets. It implements dictionaries to count the occurrences of integers in an array and words in a text file. It also implements a hash table that stores triples using keys and allows searching by key pairs. Finally, it implements a set using a hash table to store elements and supports standard set operations like add, find, remove, union, and intersect.

Uploaded by

bekaelsa172
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
You are on page 1/ 14

Ron Ahmeti

Student ID � 2203091121

Dictionaries, Hash Tables and Sets

Exercise 01: Occurrence number

Write a program that counts, in a given array of integers, the number of


occurrences of each integer.

Implementation:

using System;
using System.Collections.Generic;

class Program
{
static void Main()
{
int[] array = { 1, 2, 3, 4, 1, 2, 3, 1, 5, 6, 5, 4, 3, 2, 1 };

Dictionary<int, int> occurrences = CountOccurrences(array);

Console.WriteLine("Number of occurrences of each integer:");


foreach (var kvp in occurrences)
{
Console.WriteLine($"{kvp.Key}: {kvp.Value} times");
}
}

static Dictionary<int, int> CountOccurrences(int[] array)


{
Dictionary<int, int> occurrences = new Dictionary<int, int>();

foreach (int num in array)


{
if (occurrences.ContainsKey(num))
{
occurrences[num]++;
}
else
{
occurrences[num] = 1;
}
}

return occurrences;
}
}

Exercise 03
Write a program that counts how many times each word from a given text file
words.txt appears in it. The result words should be ordered by their number of
occurrences in the text.

Example: "This is the TEXT. Text, text, text – THIS TEXT! Is this the text?"

Result: is à 2, the à 2, this à 3, text à 6.

Solution

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;

class Program
{
static void Main()
{
string filePath = "words.txt"; // Specify the path to your text file

try
{
string text = File.ReadAllText(filePath);
var wordOccurrences = CountWordOccurrences(text);

Console.WriteLine("Result:");
foreach (var kvp in wordOccurrences.OrderByDescending(pair =>
pair.Value))
{
Console.WriteLine($"{kvp.Key} à {kvp.Value}");
}
}
catch (FileNotFoundException)
{
Console.WriteLine($"Error: File '{filePath}' not found.");
}
catch (Exception ex)
{
Console.WriteLine($"An error occurred: {ex.Message}");
}
}

static Dictionary<string, int> CountWordOccurrences(string text)


{
Dictionary<string, int> wordOccurrences = new Dictionary<string, int>();
string[] words = Regex.Split(text.ToLower(), @"\W+"); // Split words and
convert to lowercase

foreach (string word in words)


{
if (!string.IsNullOrEmpty(word))
{
if (wordOccurrences.ContainsKey(word))
{
wordOccurrences[word]++;
}
else
{
wordOccurrences[word] = 1;
}
}
}

return wordOccurrences;
}
}

Reflection and Learning:

The example demonstrates the use of File.ReadAllText to read the entire contents of
a text file.

Exercise 05

Implement a hash-table, maintaining triples (key1, key2, value) and allowing quick
search by the pair of keys and adding of triples.

Solution approach

The TripleHashTable class uses a Dictionary<(TKey1, TKey2), TValue> as the


underlying data structure to store triples.

Solution

using System;
using System.Collections.Generic;

public class TripleHashTable<TKey1, TKey2, TValue>


{
private Dictionary<(TKey1, TKey2), TValue> tripleDictionary;

public TripleHashTable()
{
tripleDictionary = new Dictionary<(TKey1, TKey2), TValue>();
}

public void Add(TKey1 key1, TKey2 key2, TValue value)


{
var key = (key1, key2);
if (!tripleDictionary.ContainsKey(key))
{
tripleDictionary.Add(key, value);
}
else
{
Console.WriteLine("Duplicate key pair. Triple not added.");
}
}

public bool TryGetValue(TKey1 key1, TKey2 key2, out TValue value)


{
var key = (key1, key2);
return tripleDictionary.TryGetValue(key, out value);
}

public void PrintAllTriples()


{
foreach (var triple in tripleDictionary)
{
Console.WriteLine($"Key1: {triple.Key.Item1}, Key2: {triple.Key.Item2},
Value: {triple.Value}");
}
}
}

class Program
{
static void Main()
{
TripleHashTable<string, int, double> tripleTable = new
TripleHashTable<string, int, double>();

// Adding triples
tripleTable.Add("John", 1, 75.5);
tripleTable.Add("Alice", 2, 89.2);
tripleTable.Add("Bob", 1, 92.7);

// Searching by key pair


if (tripleTable.TryGetValue("John", 1, out double johnGrade))
{
Console.WriteLine($"John's grade: {johnGrade}");
}
else
{
Console.WriteLine("Triple not found.");
}

// Print all triples


Console.WriteLine("All Triples:");
tripleTable.PrintAllTriples();
}
}

Exercise 07

Implement a hash-table, using "cuckoo hashing" with 3 hash-functions.

Solution

using System;

public class CuckooHashTable<TKey, TValue>


{
private const int TableSize = 10;
private const int MaxIterations = 100;

private TKey[] keys1;


private TKey[] keys2;
private TValue[] values;
private int size;

public CuckooHashTable()
{
keys1 = new TKey[TableSize];
keys2 = new TKey[TableSize];
values = new TValue[TableSize];
size = 0;
}

public void Add(TKey key, TValue value)


{
if (size == TableSize)
{
Console.WriteLine("Hash table is full. Cannot add more items.");
return;
}

for (int i = 0; i < MaxIterations; i++)


{
int index1 = HashFunction1(key);
int index2 = HashFunction2(key);

if (keys1[index1] == null)
{
keys1[index1] = key;
values[index1] = value;
size++;
return;
}

if (keys2[index2] == null)
{
keys2[index2] = key;
values[index2] = value;
size++;
return;
}

TKey displacedKey;
TValue displacedValue;

if (i % 2 == 0)
{
displacedKey = keys1[index1];
displacedValue = values[index1];
keys1[index1] = key;
values[index1] = value;
}
else
{
displacedKey = keys2[index2];
displacedValue = values[index2];
keys2[index2] = key;
values[index2] = value;
}
key = displacedKey;
value = displacedValue;
}

Console.WriteLine("Max iterations reached. Unable to find a suitable place


for the item.");
}

public TValue Get(TKey key)


{
int index1 = HashFunction1(key);
int index2 = HashFunction2(key);

if (keys1[index1] != null && keys1[index1].Equals(key))


{
return values[index1];
}

if (keys2[index2] != null && keys2[index2].Equals(key))


{
return values[index2];
}

return default(TValue);
}

private int HashFunction1(TKey key)


{
return Math.Abs(key.GetHashCode() % TableSize);
}

private int HashFunction2(TKey key)


{
return Math.Abs((key.GetHashCode() * 17) % TableSize);
}
}

class Program
{
static void Main()
{
CuckooHashTable<string, int> cuckooHashTable = new CuckooHashTable<string,
int>();

cuckooHashTable.Add("One", 1);
cuckooHashTable.Add("Two", 2);
cuckooHashTable.Add("Three", 3);
cuckooHashTable.Add("Four", 4);
cuckooHashTable.Add("Five", 5);
cuckooHashTable.Add("Six", 6);

Console.WriteLine("Value for key 'Two': " + cuckooHashTable.Get("Two"));


Console.WriteLine("Value for key 'Four': " + cuckooHashTable.Get("Four"));
Console.WriteLine("Value for key 'Seven': " +
cuckooHashTable.Get("Seven"));
}
}
Exercise 09:

Implement the data structure "Set" in a class HashedSet<T>, using your class
HashTable<K, T> to hold the elements. Implement all standard set operations like
Add(T), Find(T), Remove(T), Count, Clear(), union and intersect.
.

Solution

using System;
using System.Collections.Generic;
using System.Linq;

public class HashedSet<T>


{
private HashTable<T, T> hashTable;

public HashedSet()
{
hashTable = new HashTable<T, T>();
}

public void Add(T item)


{
hashTable[item] = item;
}

public bool Find(T item)


{
try
{
hashTable.Find(item);
return true;
}
catch (KeyNotFoundException)
{
return false;
}
}

public void Remove(T item)


{
hashTable.Remove(item);
}

public int Count => hashTable.Count;

public void Clear()


{
hashTable.Clear();
}

public HashedSet<T> Union(HashedSet<T> otherSet)


{
HashedSet<T> unionSet = new HashedSet<T>();
foreach (var item in this)
{
unionSet.Add(item);
}

foreach (var item in otherSet)


{
unionSet.Add(item);
}

return unionSet;
}

public HashedSet<T> Intersect(HashedSet<T> otherSet)


{
HashedSet<T> intersectSet = new HashedSet<T>();
foreach (var item in this)
{
if (otherSet.Find(item))
{
intersectSet.Add(item);
}
}

return intersectSet;
}

public IEnumerator<T> GetEnumerator()


{
foreach (var entry in hashTable)
{
yield return entry.Key;
}
}
}

class Program
{
static void Main()
{
HashedSet<int> set1 = new HashedSet<int>();
set1.Add(1);
set1.Add(2);
set1.Add(3);

HashedSet<int> set2 = new HashedSet<int>();


set2.Add(2);
set2.Add(3);
set2.Add(4);

// Union of sets
HashedSet<int> unionSet = set1.Union(set2);
Console.WriteLine("Union of sets: " + string.Join(", ", unionSet));

// Intersection of sets
HashedSet<int> intersectSet = set1.Intersect(set2);
Console.WriteLine("Intersection of sets: " + string.Join(", ",
intersectSet));

// Removing an element
set1.Remove(2);
// Count of elements
Console.WriteLine("Count of elements in set1: " + set1.Count);

// Clearing the set


set1.Clear();
Console.WriteLine("Count after clearing set1: " + set1.Count);
}
}

Reflection and Learning:

Overall, this exercise enhances understanding of data structure design, reuse of


existing components, and the practical application of set operations in a real-
world scenario.

Exercise 11

* Define TreeMultiSet<T> class, which allows to keep a set of elements, in


increasing order and to have duplicates of the elements. Implement operations
adding of element, finding the number of occurrences, deletion, iterator, min / max
element finding, min / max deletion. Implement the possibility to pass an external
Comparer<T> for elements comparison.

Solution

using System;
using System.Collections;
using System.Collections.Generic;

public class TreeMultiSet<T> : IEnumerable<T>


{
private readonly List<T> elements;
private readonly IComparer<T> comparer;

public TreeMultiSet() : this(null) { }

public TreeMultiSet(IComparer<T> comparer)


{
this.elements = new List<T>();
this.comparer = comparer ?? Comparer<T>.Default;
}

public void Add(T element)


{
int index = FindInsertionIndex(element);
elements.Insert(index, element);
}

public int CountOccurrences(T element)


{
int count = 0;
foreach (T e in elements)
{
if (comparer.Compare(e, element) == 0)
count++;
}
return count;
}

public bool Remove(T element)


{
int index = FindFirstOccurrenceIndex(element);
if (index != -1)
{
elements.RemoveAt(index);
return true;
}
return false;
}

public IEnumerator<T> GetEnumerator()


{
return elements.GetEnumerator();
}

IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}

public T Min()
{
if (elements.Count == 0)
throw new InvalidOperationException("The set is empty.");

return elements[0];
}

public T Max()
{
if (elements.Count == 0)
throw new InvalidOperationException("The set is empty.");

return elements[elements.Count - 1];


}

public void DeleteMin()


{
if (elements.Count > 0)
elements.RemoveAt(0);
}

public void DeleteMax()


{
if (elements.Count > 0)
elements.RemoveAt(elements.Count - 1);
}

private int FindInsertionIndex(T element)


{
return elements.BinarySearch(element, comparer);
}

private int FindFirstOccurrenceIndex(T element)


{
int index = elements.BinarySearch(element, comparer);
if (index < 0)
return -1;

while (index > 0 && comparer.Compare(elements[index - 1], element) == 0)


index--;

return index;
}
}

class Program
{
static void Main()
{
// Example usage of TreeMultiSet
TreeMultiSet<int> treeMultiSet = new TreeMultiSet<int>();

treeMultiSet.Add(3);
treeMultiSet.Add(1);
treeMultiSet.Add(2);
treeMultiSet.Add(3);
treeMultiSet.Add(1);

Console.WriteLine("Occurrences of 1: " + treeMultiSet.CountOccurrences(1));


Console.WriteLine("Occurrences of 3: " + treeMultiSet.CountOccurrences(3));

Console.WriteLine("Min element: " + treeMultiSet.Min());


Console.WriteLine("Max element: " + treeMultiSet.Max());

Console.WriteLine("Removing 1: " + treeMultiSet.Remove(1));


Console.WriteLine("Occurrences of 1 after removal: " +
treeMultiSet.CountOccurrences(1));

Console.WriteLine("After deletion of min:");


treeMultiSet.DeleteMin();
foreach (var element in treeMultiSet)
{
Console.WriteLine(element);
}

Console.WriteLine("After deletion of max:");


treeMultiSet.DeleteMax();
foreach (var element in treeMultiSet)
{
Console.WriteLine(element);
}
}
}

Exercise 13

* We are given a sequence P containing L integers L (1 < L < 50,000) and a number
N. We call a “lucky sub-sequence within P” every sub-sequence of integers from P
with a sum equal to N.

Imagine we have a sequence S, holding all the lucky sub-sequences of P, kept in


decreasing order by their length. When the length is the same, the sequences are
ordered in decreasing order by their elements: from the leftmost to the rightmost.
Write a program to return the first 10 elements of S.

Example: We are given N = 5 and the sequence P = {1, 1, 2, 1, -1, 2, 3, -1, 1, 2,


3, 5, 1, -1, 2, 3}. The sequence S consists of the following 13 sub-sequences of P:

- [1, -1, 2, 3, -1, 1]

- [1, 2, 1, -1, 2]

- [3, -1, 1, 2]

- [2, 3, -1, 1]

- [1, 1, 2, 1]

- [1, -1, 2, 3]

- [1, -1, 2, 3]

- [-1, 1, 2, 3]

- [5, 1, -1]

- [2, 3]

- [2, 3]

- [2, 3]

- [5]

The last 10 elements of P are given in bold.

Solution Approach

This program defines a LuckySubsequences class with a Main method showcasing the
example sequence P and number N. The FindLuckySubsequences method generates all
sub-sequences of P and filters those with a sum equal to N. It then orders the
lucky sub-sequences by length and elements. The GetFirst10Elements method flattens
the list of sequences and takes the first 10 elements. The result is displayed in
the console.

Solution

using System;
using System.Collections.Generic;
using System.Linq;

class LuckySubsequences
{
static void Main()
{
// Example sequence P and number N
int[] P = { 1, 1, 2, 1, -1, 2, 3, -1, 1, 2, 3, 5, 1, -1, 2, 3 };
int N = 5;

// Find lucky sub-sequences


List<List<int>> luckySubsequences = FindLuckySubsequences(P, N);

// Get the first 10 elements of S


List<int> result = GetFirst10Elements(luckySubsequences);

// Display the result


Console.WriteLine("The first 10 elements of S:");
Console.WriteLine(string.Join(", ", result));
}

static List<List<int>> FindLuckySubsequences(int[] P, int N)


{
List<List<int>> luckySubsequences = new List<List<int>>();

// Generate all sub-sequences of P


for (int i = 0; i < (1 << P.Length); i++)
{
List<int> subsequence = new List<int>();
int sum = 0;

for (int j = 0; j < P.Length; j++)


{
if ((i & (1 << j)) != 0)
{
subsequence.Add(P[j]);
sum += P[j];
}
}

if (sum == N)
{
luckySubsequences.Add(subsequence);
}
}

// Order lucky sub-sequences by length and then by elements


luckySubsequences = luckySubsequences
.OrderByDescending(seq => seq.Count)
.ThenByDescending(seq => seq)
.ToList();

return luckySubsequences;
}

static List<int> GetFirst10Elements(List<List<int>> sequences)


{
List<int> result = new List<int>();

// Flatten the list of sequences and take the first 10 elements


foreach (var sequence in sequences.Take(10))
{
result.AddRange(sequence);
}

return result;
}
}
Testing &amp; Output:
- Shortest path from vertex 0 to vertex 5:
0 1 3 5

You might also like