Skip to content

Commit 5210294

Browse files
ClémentClément
authored andcommitted
Separating prelim for dictionary, working on explanations.
1 parent 4d217f3 commit 5210294

5 files changed

Lines changed: 216 additions & 91 deletions

File tree

Lines changed: 51 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,59 @@
1-
/*
2-
* Why prime numbers are needed is explained for example
3-
* at
4-
* https://cs.stackexchange.com/questions/11029
5-
*/
6-
71
public static class PrimeHelper
82
{
9-
public static bool IsPrime(int n)
10-
{
11-
// "A prime number is a natural number greater than 1 that is not a product of two smaller natural numbers."
12-
// https://en.wikipedia.org/wiki/Prime_number
13-
if (n < 2)
14-
return false;
15-
if (n == 2 || n == 3)
16-
return true;
17-
if (n % 2 == 0)
18-
return false;
19-
for (int i = 3; i * i <= n; i += 2)
20-
if (n % i == 0)
21-
return false;
22-
return true;
23-
}
24-
25-
public static int NextPrime(int n)
26-
{
27-
if (n < 2)
3+
public static bool IsPrime(int n)
284
{
29-
n = 2;
5+
bool returned = true;
6+
if (n < 2)
7+
returned = false;
8+
if (n == 2 || n == 3)
9+
returned = true;
10+
if (n % 2 == 0)
11+
returned = false;
12+
// We use uint so that we can compute larger primes, since
13+
// we know that i will not need to be negative.
14+
uint i = 3;
15+
16+
/*
17+
* Our goal is to find i > 1 and j > 1 such that
18+
* i * j = n
19+
* to prove that n is not prime.
20+
* Assuming i <= j, it suffices to look "up to" i * i <= n (i.e, so that i is less than √n).
21+
* We also exit our loop as soon as returned is proved false.
22+
*/
23+
24+
while (i * i <= n && returned)
25+
{
26+
if (n % i == 0)
27+
returned = false;
28+
i += 2;
29+
}
30+
return returned;
3031
}
31-
else
32+
33+
public static int NextPrime(int n)
3234
{
33-
// Since 2 is the only even prime,
34-
// we make the n even if it is divisible
35-
// by 2.
36-
if (n % 2 == 0)
37-
n++;
35+
int returned = n;
36+
if (returned <= 2)
37+
{
38+
// The smallest prime greater than or equal to 2
39+
// is … 2!
40+
returned = 2;
41+
}
42+
else
43+
{
44+
// Since 2 is the only even prime,
45+
// we make the returned value even
46+
// if it is divisible by 2.
47+
if (returned % 2 == 0)
48+
returned++;
3849

39-
while (!IsPrime(n))
40-
{
41-
n += 2;
42-
}
50+
// Then, we simply look for the next Prime value,
51+
// incrementing two by two.
52+
while (!IsPrime(returned))
53+
{
54+
returned += 2;
55+
}
56+
}
57+
return returned;
4358
}
44-
return n;
45-
}
4659
}

source/code/projects/Dictionary/Dictionary/Program.cs

Lines changed: 0 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -3,58 +3,8 @@
33

44
class Program
55
{
6-
/*
7-
* Demonstrating how to use
8-
* enum type, cf.
9-
* https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/enum
10-
*/
11-
public enum Level
12-
{
13-
Low,
14-
Medium,
15-
High
16-
}
17-
186
static void Main(string[] args)
197
{
20-
// Demonstrating enum type.
21-
Level lvl1 = Level.Medium; // To access the value, we prefix with Level.
22-
Level lvl2 = (Level)0; // We can cast an int into a Level.
23-
Console.WriteLine(lvl1 + " " + lvl2);
24-
// Will display "Medium Low"
25-
26-
// Demonstrating PrimeHelper class:
27-
for (int i = 0; i < 10; i++)
28-
{
29-
Console.WriteLine(
30-
"The smallest prime greater than or equal to "
31-
+ i
32-
+ " is "
33-
+ PrimeHelper.NextPrime(i)
34-
+ "."
35-
);
36-
}
37-
38-
// Demonstrating GetHashCode:
39-
Console.WriteLine(
40-
"The hash code of an empty array of 12 int is: "
41-
+ (new int[12]).GetHashCode()
42-
+ "."
43-
);
44-
Console.WriteLine(
45-
"The hash code of an empty array of 14 string is: "
46-
+ (new string[14]).GetHashCode()
47-
+ "."
48-
);
49-
Console.WriteLine(
50-
"The hash code of \"test string\" is: "
51-
+ "test string".GetHashCode()
52-
+ "."
53-
);
54-
Console.WriteLine(
55-
"The hash code of 12 is: " + 12.GetHashCode() + "."
56-
);
57-
588
// Example of using the CDictionary class
599
CDictionary<string, int> ht = new CDictionary<
6010
string,
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
public static class PrimeHelper
2+
{
3+
public static bool IsPrime(int n)
4+
{
5+
bool returned = true;
6+
if (n < 2)
7+
returned = false;
8+
if (n == 2 || n == 3)
9+
returned = true;
10+
if (n % 2 == 0)
11+
returned = false;
12+
// We use uint so that we can compute larger primes, since
13+
// we know that i will not need to be negative.
14+
uint i = 3;
15+
16+
/*
17+
* Our goal is to find i > 1 and j > 1 such that
18+
* i * j = n
19+
* to prove that n is not prime.
20+
* Assuming i <= j, it suffices to look "up to" i * i <= n (i.e, so that i is less than √n).
21+
* We also exit our loop as soon as returned is proved false.
22+
*/
23+
24+
while (i * i <= n && returned)
25+
{
26+
if (n % i == 0)
27+
returned = false;
28+
i += 2;
29+
}
30+
return returned;
31+
}
32+
33+
public static int NextPrime(int n)
34+
{
35+
int returned = n;
36+
if (returned <= 2)
37+
{
38+
// The smallest prime greater than or equal to 2
39+
// is … 2!
40+
returned = 2;
41+
}
42+
else
43+
{
44+
// Since 2 is the only even prime,
45+
// we make the returned value even
46+
// if it is divisible by 2.
47+
if (returned % 2 == 0)
48+
returned++;
49+
50+
// Then, we simply look for the next Prime value,
51+
// incrementing two by two.
52+
while (!IsPrime(returned))
53+
{
54+
returned += 2;
55+
}
56+
}
57+
return returned;
58+
}
59+
}
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
using System;
2+
using System.Collections.Generic;
3+
4+
class Program
5+
{
6+
public enum Level
7+
{
8+
Low,
9+
Medium,
10+
High
11+
}
12+
13+
static void Main(string[] args)
14+
{
15+
// Demonstrating enum type.
16+
Console.WriteLine("Demonstrating enumerated types:");
17+
Level lvl1 = Level.Medium; // To access the value, we prefix with Level.
18+
Level lvl2 = (Level)0; // We can cast an int into a Level.
19+
Console.WriteLine(lvl1);
20+
Console.WriteLine(lvl2.ToString());
21+
// Will display "Medium" then "Low": the ToString() method is given by default.
22+
23+
// Demonstrating PrimeHelper class:
24+
Console.WriteLine("\nDemonstrating PrimeHelper class:");
25+
// Testing IsPrime
26+
int[] testingValues = { 89, 6700417, 2147483646, 2147483647 };
27+
// 2147483647 remained the largest known prime until 1867,
28+
// and is the largest value that a signed 32-bit integer field can hold!
29+
// cf. https://en.wikipedia.org/wiki/2,147,483,647
30+
foreach (int i in testingValues)
31+
{
32+
Console.WriteLine($"{i:N00} is prime: {PrimeHelper.IsPrime(i)}.");
33+
}
34+
// Testing NextPrime
35+
for (int i = 0; i < 10; i++)
36+
{
37+
Console.WriteLine(
38+
"The smallest prime greater than or equal to "
39+
+ i
40+
+ " is "
41+
+ PrimeHelper.NextPrime(i)
42+
+ "."
43+
);
44+
}
45+
Console.WriteLine("The smallest prime greater than or equal to 2,147,483,000 is: " + PrimeHelper.NextPrime(2147483000));
46+
47+
// Demonstrating GetHashCode:
48+
Console.WriteLine("\nDemonstrating GetHashCode method:");
49+
Console.WriteLine(
50+
"The hash code of an empty array of 12 int is: "
51+
+ (new int[12]).GetHashCode() // 156563611
52+
+ "."
53+
);
54+
Console.WriteLine(
55+
"The hash code of an empty array of 14 string is: "
56+
+ (new string[14]).GetHashCode() // -800837957
57+
+ "."
58+
);
59+
Console.WriteLine(
60+
"The hash code of \"test string\" is: "
61+
+ "test string".GetHashCode() // 1040790544
62+
+ "."
63+
);
64+
Console.WriteLine(
65+
"The hash code of 12 is: " + 12.GetHashCode() + "." // 12
66+
);
67+
}
68+
}

source/lectures/data/dictionary.md

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,14 +28,40 @@ Generally, it has operations to…
2828

2929
And, very importantly, it uses
3030

31-
- *a hash function*, which transforms the key into an `int` (its *hash*), used as an array index,
32-
- *a collision resolution strategy*, which handles when two *different* keys have been assigned the same hash by the hash function.
31+
- *a hash function*, which transforms the key into an `int` (its *hash*), used as to produce an array index,
32+
- *a collision resolution strategy*, which handles when two *different* keys have been assigned the same index.
33+
34+
### Overview
35+
36+
A dictionary organises the key-value pairs into an array by storing it in its corresponding index, computed using the hash of the key.
37+
The main benefit of this approach is that looking if a key-value pair is already in the dictionary is immediate: it suffices to hash the key, and to look at the index obtained if the same key is already stored.
38+
The main downside is that *multiple (different) keys can be assigned the same hash, and hence the same index*: indeed, since the keys that will be used is not known ahead of time, it is possible that different keys are assigned the same index. This is a *collision*, and there are two main ways of resolving it:
39+
40+
- One can use [chaining](https://en.wikibooks.org/wiki/Data_Structures/Hash_Tables#Chaining) so that the array actually contains *lists* of key-value pairs.
41+
- One case use [open addressing](https://en.wikibooks.org/wiki/Data_Structures/Hash_Tables#Open_addressing) so that "the next available index" is used.
3342

3443
## Possible Implementation
3544

45+
### Preliminaries
46+
47+
Implementing dictionaries requires some preliminaries: prime numbers, [enumerated types](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/enum), and the built-in [`GetHashCode` method](https://learn.microsoft.com/en-us/dotnet/api/system.object.gethashcode).
48+
49+
We first illustrate prime numbers with the following class, [remembering that](https://en.wikipedia.org/wiki/Prime_number)
50+
51+
> A prime number is a natural number greater than 1 that is not a product of two smaller natural numbers.
52+
53+
```{download="./code/projects/Dictionary_prelim.zip"}
54+
!include code/projects/Dictionary_prelim/Dictionary_prelim/PrimeHelper.cs
55+
```
56+
57+
We can then declare a `Level` enumerated type, and demonstrate how to use it, our PrimeHelper `static` class, and a couple of examples using `GetHashCode`:
58+
59+
```{download="./code/projects/Dictionary_prelim.zip"}
60+
!include code/projects/Dictionary_prelim/Dictionary_prelim/Program.cs
61+
```
62+
3663
### Using Open Addressing
3764

38-
A description is given at <https://en.wikibooks.org/wiki/Data_Structures/Hash_Tables#Open_addressing>.
3965

4066
```{download="./code/projects/Dictionary.zip"}
4167
!include code/projects/Dictionary/Dictionary/Dictionary.cs
@@ -48,3 +74,12 @@ A description is given at <https://en.wikibooks.org/wiki/Data_Structures/Hash_Ta
4874
```{download="./code/projects/Dictionary.zip"}
4975
!include code/projects/Dictionary/Dictionary/Program.cs
5076
```
77+
78+
79+
<!--
80+
/*
81+
* Why prime numbers are needed is explained for example
82+
* at
83+
* https://cs.stackexchange.com/questions/11029
84+
*/
85+
-->

0 commit comments

Comments
 (0)