Beispiel #1
0
func (c *cache) concatsToPrime(x, y int) bool {
	key := strconv.Itoa(x) + strconv.Itoa(y)
	c.Lock()
	defer c.Unlock()
	// Try to find the answer in the cache.
	if val, ok := c.m[key]; ok {
		return val
	}
	// Otherwise find it manually and add to the cache.
	xstr, ystr := strconv.Itoa(x), strconv.Itoa(y)
	a, _ := strconv.Atoi(xstr + ystr)
	b, _ := strconv.Atoi(ystr + xstr)
	val := tools.IsPrime(a) && tools.IsPrime(b)
	c.m[key] = val
	return val
}
Beispiel #2
0
// The search space is too large for brute-force. So, note that we are seeking
// roughly the inverse of the previous problem -- to minimize n/phi(n).
// Therefore, we want to maximize phi(n), which is acheived for numbers with
// the fewest and largest unique prime factors. But the number cannot simply be
// prime because in that case phi(n) == n-1 which is not a permutation of n.
// Therefore, the best candidates should have two unique prime factors.
func problem70() int {
	// Since we are seeking large values for both prime factors, we can
	// search among numbers close to the value of sqrt(1e7) ~ 3162
	var primes []int
	for i := 2000; i < 4000; i++ {
		if tools.IsPrime(i) {
			primes = append(primes, i)
		}
	}

	// Keep track of the minimal n/phi(n) ratio found
	// and the value of n that produced it.
	min := math.Inf(1)
	res := 0

	const limit = 10000000
	for _, x := range primes {
		for _, y := range primes {
			if n := x * y; n < limit && x != y {
				if pn := tools.Phi(n); isPerm(n, pn) {
					if rat := float64(n) / float64(pn); rat < min {
						min = rat
						res = n
					}
				}
			}
		}
	}
	return res
}
Beispiel #3
0
// Return a new slice holding only the elements of xs that are prime.
func filterPrime(xs []int) []int {
	var ys []int
	for _, x := range xs {
		if tools.IsPrime(x) {
			ys = append(ys, x)
		}
	}
	return ys
}
Beispiel #4
0
// problem51 loops over ints from 56995 to inf, returning the smallest member
// of an 8-prime family.
func problem51() int {
	n := 56995 // given in the description as a member of a 7-prime family
	for {
		if tools.IsPrime(n) && isSmallestMember(n) {
			return n
		}
		n++
	}
}
Beispiel #5
0
// Note that the phi function multiplies n by (1 - (1/p)) for every p in
// its unique prime factors. Therefore, phi(n) will diminish as n has a greater
// number of small unique prime factors. Since we are seeking the largest value
// for n/phi(n), we want to minimize phi(n). We are therefore looking for the
// largest number <= 1e6 which is the product of the smallest unique prime
// factors, i.e successive prime numbers starting from 2.
func problem69() int {
	limit := 1000000
	candidate := 1 // The multiplicative identity.
	for i := 2; i*candidate <= limit; i++ {
		if tools.IsPrime(i) {
			candidate *= i
		}
	}
	return candidate
}
Beispiel #6
0
// isSmallestMember checks whether the given number satisfies the problem
// description: is it the smallest member of an 8-prime family?
func isSmallestMember(n int) bool {
	for _, indices := range findIndices(n) {
		var primes []int
		for _, x := range family(n, indices) {
			if tools.IsPrime(x) {
				primes = append(primes, x)
			}
		}
		if len(primes) == 8 {
			return true
		}
	}
	return false
}
Beispiel #7
0
func problem77() int {
	var primes []int
	for i := 2; i < 100; i++ {
		if tools.IsPrime(i) {
			primes = append(primes, i)
		}
	}

	// What is the first value which can be written as the sum of primes in
	// over five thousand different ways?
	for i := 2; ; i++ {
		if x := numPartitions(i, primes); x > 5000 {
			return i
		}
	}
}
Beispiel #8
0
// We are going to use a concurrent depth-first search with a worker goroutine
// pool of 4. Each goroutine will search for a solution from a different
// starting prime. As soon as a solution is found, we return from the function.
// Otherwise, we wait for all starting primes to be checked, and return an
// error.
func problem60() (int, error) {
	// It's not clear how many primes to search through. Experimentation
	// suggests a limit of 9000 produces the correct answer: 26033. Note
	// our algorithm does not guarantee the solution is the smallest
	// possible, but as a matter of fact, it is. We could verify our
	// answer by raising the limit to 26033, searching exhaustively, and
	// observing that no smaller solutions are found.
	limit := 9000
	var primes []int
	for i := 0; i < limit; i++ {
		if tools.IsPrime(i) {
			primes = append(primes, i)
		}
	}

	c := newCache()
	ans := make(chan int)   // Used to send the answer.
	done := make(chan bool) // Used to signal that all worker goroutines are done.
	pchan := make(chan int) // Used to send worker goroutines a starting prime to search.
	var wg sync.WaitGroup

	// Woker goroutine pool of 4.
	for i := 0; i < 4; i++ {
		wg.Add(1)
		go func() {
			for {
				p, ok := <-pchan
				if !ok {
					wg.Done()
					return
				}

				// Perform depth-first search starting at the given prime.
				var frontier tools.Stack
				frontier.Push(Node{p})

				for len(frontier) != 0 {
					n := frontier.Pop().(Node)
					if len(n) == 5 {
						ans <- tools.Sum(n...)
					}
					for _, prime := range primes {
						child := append(append(*new(Node), n...), prime)
						if prime > tools.Max(n...) && c.allConcatToPrime(child) {
							frontier.Push(child)
						}
					}
				}
			}
		}()
	}

	go func() {
		for _, p := range primes {
			pchan <- p
		}
		close(pchan)
		wg.Wait()    // Wait for all workers to complete their search
		done <- true // before sending completion signal.
	}()

	for {
		select {
		case x := <-ans:
			return x, nil
		case <-done:
			return -1, fmt.Errorf("problem60: no solution found with limit %v", limit)
		}
	}
}