package main
import (
	"fmt"
)

type PrimeGenerator struct {
	Next func() uint32
}

func NewPrimeGenerator() *PrimeGenerator {
	primeGenerator := PrimeGenerator{}
	
	multiples := map[uint32]uint32{}
	wheelCycle := []uint32{10, 2, 4, 2, 4, 6, 2, 6, 4, 2, 4, 6, 6, 2, 6, 4, 2, 6, 4, 6, 8, 4, 2, 4, 2, 4, 8, 6, 4, 6, 2, 4, 6, 2, 6, 6, 4, 2, 4, 6, 2, 6, 4, 2, 4, 2, 10, 2}
	var num uint32
	var i uint32 = 0
	primeGenerator.Next = func() uint32 {
		if num == 0 {
			num = 2
			return 2
		}
		if num == 2 {
			num = 3
			return 3
		}
		if num == 3 {
			num = 5
			return 5
		}
		if num == 5 {
			num = 1
			return 7
		}
		
		for ; ; {
			num += wheelCycle[i]
			i = (i + 1) % 48
			
			factor, hasFactor := multiples[num]
			var k uint32
			if hasFactor {
				delete(multiples, num)
				
				switch (num / factor) % 210{
				case 1: k = 0
				case 11: k = 1
				case 13: k = 2
				case 17: k = 3
				case 19: k = 4
				case 23: k = 5
				case 29: k = 6
				case 31: k = 7
				case 37: k = 8
				case 41: k = 9
				case 43: k = 10
				case 47: k = 11
				case 53: k = 12
				case 59: k = 13
				case 61: k = 14
				case 67: k = 15
				case 71: k = 16
				case 73: k = 17
				case 79: k = 18
				case 83: k = 19
				case 89: k = 20
				case 97: k = 21
				case 101: k = 22
				case 103: k = 23
				case 107: k = 24
				case 109: k = 25
				case 113: k = 26
				case 121: k = 27
				case 127: k = 28
				case 131: k = 29
				case 137: k = 30
				case 139: k = 31
				case 143: k = 32
				case 149: k = 33
				case 151: k = 34
				case 157: k = 35
				case 163: k = 36
				case 167: k = 37
				case 169: k = 38
				case 173: k = 39
				case 179: k = 40
				case 181: k = 41
				case 187: k = 42
				case 191: k = 43
				case 193: k = 44
				case 197: k = 45
				case 199: k = 46
				case 209: k = 47
				}
			} else {
				factor = num
			}
			
			for newNum := num + factor * wheelCycle[k]; ; newNum += factor * wheelCycle[k] {
				_, hasNewFactor := multiples[newNum]
				if !hasNewFactor {
					multiples[newNum] = factor
					break
				}
				k = (k + 1) % 48
			}
			
			if !hasFactor {
				return num
			}
		}
	}
	
	return &primeGenerator
}

func main() {
	n := 1000000
	primeGenerator := NewPrimeGenerator()
	for i := 1; i < n; i++ {
		primeGenerator.Next()
	}
	fmt.Printf("%d番目の素数: %d", n, primeGenerator.Next())
}