Skip to content

Commit

Permalink
do project euler for fun, time consuming
Browse files Browse the repository at this point in the history
  • Loading branch information
Guangming Wang committed May 11, 2020
1 parent eea6eb8 commit 84431ec
Show file tree
Hide file tree
Showing 13 changed files with 648 additions and 0 deletions.
57 changes: 57 additions & 0 deletions algorithm/projecteuler/p112/p112.go
@@ -0,0 +1,57 @@
package main

import (
"fmt"
)

func main() {
fmt.Println("start")
fmt.Println(p112(99))
}

//rate为百分比值,整数,比如50表示50%
func p112(rate int) int {
bouncyCount := 0
positive := 1
for {
if IsBouncyNum(positive) {
bouncyCount++
}
if bouncyCount * 100 == positive * rate {
return positive
}
positive++
}
}

func IsIncrNum(n int) bool {
currDigit := n % 10
n = n / 10
for n != 0 {
nextDigit := n % 10
if nextDigit > currDigit {
return false
}
currDigit = nextDigit
n = n / 10
}
return true
}

func IsDecrNum(n int) bool {
currDigit := n % 10
n = n / 10
for n != 0 {
nextDigit := n % 10
if nextDigit < currDigit {
return false
}
currDigit = nextDigit
n = n / 10
}
return true
}

func IsBouncyNum(n int) bool {
return !IsIncrNum(n) && !IsDecrNum(n)
}
66 changes: 66 additions & 0 deletions algorithm/projecteuler/p120/p120.go
@@ -0,0 +1,66 @@
package main

import (
"fmt"
"math/big"
)

func main() {
fmt.Println(p120(3, 1000))
//fmt.Println(ReminderMax(700))
}

func p120(start, end int) int {
var rMaxSum int
for i:=start; i<=end; i++ {
rMaxSum += ReminderMax(i)
}
return rMaxSum
}

func ReminderMax(in int) int {
var a = big.NewInt(int64(in))
var array []int64
var power, aLeft, aRight, n big.Int
var pointer, maxIndex int
power.Exp(a, big.NewInt(2), nil)
aLeft.Sub(a, big.NewInt(1))
aRight.Add(a, big.NewInt(1))
//rMax := 0
n.SetInt64(1)
for {
ps := PowerSum(&aLeft, &aRight, &n)
array = append(array, ps.Mod(ps, &power).Int64())
if maxIndex !=0 && array[pointer] == array[maxIndex] {
pointer++
} else {
pointer = 0
}
// 如果队列中有3个重复的数,则认为已经进入了循环
if pointer >= 3{
break
}
n.Add(&n, big.NewInt(1))
maxIndex++
}
return int(ArrayMax(array))
}

//go居然没有好用的整数求幂运算符
func PowerSum(x, y, p *big.Int) *big.Int {
var rx, ry big.Int
rx.Exp(x, p, nil)
ry.Exp(y, p, nil)
return rx.Add(&rx, &ry)
}

//找到数组中最大的数
func ArrayMax(array []int64) int64 {
var max int64 = 0
for _, i := range array {
if max < i {
max = i
}
}
return max
}
136 changes: 136 additions & 0 deletions algorithm/projecteuler/p549/p549.go
@@ -0,0 +1,136 @@
package main

import "fmt"

func main() {
//fmt.Println(FirstFactorialDivisibleBy(25))
//var factorial, prime int = 4, 2
//fmt.Println(PrimeCount(factorial, prime))
//fmt.Println(PrimeCountRecursion(factorial, prime))
//fmt.Println(HighestPowerDividesFactorial(factorial, prime))
fmt.Println(p549(100000))
}

//还没有得到答案
func p549(n int) int {
if n < 2 {
return 0
}
var sum int
for i := 2; i <= n; i++ {
temp := FirstFactorialDivisibleBy(i)
sum += temp
}
return sum
}

func GreatestCommonDivisor(x, y int) int {
if x % y == 0 {
return y
}
return GreatestCommonDivisor(y, x % y)
}

func FactorialLimit(n int) int {
var limit int
divs := Divisor(n)
for divisor, exp := range divs {
temp := ExpFactorialLimit(divisor, exp)
if limit < ExpFactorialLimit(divisor, exp) {
limit = temp
}
}
return limit
}

//PrimeCount返回n!中包含prime因数的个数
//比如 4! 中包含3个2,则 PrimeCount(4, 2) -> 3
//自己通过规律推算的,求相关数学理论:)
//see HighestPowerDividesFactorial
func PrimeCount(n, prime int) int {
var count int
for n >= prime {
count += n / prime
n = n / prime
}
return count
}

//PrimeCountRecursion 是 PrimeCount的递归版本
func PrimeCountRecursion(n, prime int) int {
if n < prime {
return 0
}
if n == prime {
return 1
}
return n / prime + PrimeCount(n/prime, prime)
}

//PrimeCount的简化版
//https://undergroundmathematics.org/divisibility-and-induction/factorial-fun/solution
func HighestPowerDividesFactorial(n, p int) int {
var power, div int
div = p
for div <= n {
power = power + n/div
div = div*p
}
return power
}

//ExpFactorialLimit 返回能够整除x**y的阶乘的最后一个乘数
//比如 5**2 最小能够被10的阶乘整除 FactorialLimit(5, 2) -> 10
//使用的逆推法,十分的不高效
func ExpFactorialLimit(x, y int) int {
var start int
start = x*y-y/x*x
for {
if PrimeCount(start, x) >= y {
return start
}
start += x
}
}

//Divisor返回一个x的除数map,key为除数,value为除数的个数
func Divisor(x int) map[int]int {
var divisor = make(map[int]int)
for {
if x % 2 == 0 {
x = x / 2
divisor[2]++
} else {
break
}
}
for i := 3; i <= x; i=i+2 {
for {
if x % i == 0 {
x = x / i
divisor[i]++
} else {
break
}
}
}
return divisor
}

//这个算法也不是很高效
//https://www.geeksforgeeks.org/find-first-natural-number-whose-factorial-divisible-x/
func FirstFactorialDivisibleBy(n int) int {
var f int = 1
var temp int = n
for f = 1; f <= n; f++ {
temp = temp / GreatestCommonDivisor(f, temp)
if temp == 1 {
break
}
}
return f
}

//有个人解了300多道题,可以作为参考
//https://en.wikipedia.org/wiki/Kempner_function
//https://euler.stephan-brumme.com/549/
65 changes: 65 additions & 0 deletions algorithm/projecteuler/p87/p87.go
@@ -0,0 +1,65 @@
package main

import (
"fmt"
"math"
)

func main() {
fmt.Println(P87(50000000))
}

func P87(n int) int {
primeUplimit := int(math.Sqrt(float64(n)))
primes := PrimeGriddle(primeUplimit)
var power2, power3, power4 []int
for _, p := range primes {
temp := p * p
power2 = append(power2, temp)
temp *= p
if temp < n {
power3 = append(power3, temp)
}
temp *= p
if temp < n {
power4 = append(power4, temp)
}
}
var result = make(map[int]bool)
for _, i := range power2 {
for _, j := range power3 {
if i + j >= n {
break
}
for _, k := range power4 {
if i + j + k >= n {
break
}
result[i+j+k] = true
}
}
}
//fmt.Println(result)
return len(result)
}


// return prime number array below number n
func PrimeGriddle(n int) []int {
var temp = make([]int, n+1)
for i:= 2; i <= n; i++ {
temp[i] = i
}
for i :=2; i <= n; i++ {
for j := 2; i*j <= n; j++ {
temp[i*j] = 0
}
}
var primes []int
for i := 2; i <= n; i++ {
if temp[i] != 0 {
primes = append(primes, temp[i])
}
}
return primes
}
File renamed without changes.
File renamed without changes.
File renamed without changes.
26 changes: 26 additions & 0 deletions algorithm/sinknum/sinknum.go
@@ -0,0 +1,26 @@
package main

import (
"fmt"
)

func main() {
fmt.Println("start")
}

func NumberSink(array []int) []int {
countZero := 0
lastNonZero := 0
for i := 0; i < len(array); i++ {
if array[i] == 0 {
countZero++
} else {
array[lastNonZero] = array[i]
lastNonZero++
}
}
for j := lastNonZero+1; j < len(array); j++{
array[j] = 0
}
return array
}
42 changes: 42 additions & 0 deletions algorithm/sinknum/sinknum_test.go
@@ -0,0 +1,42 @@
package main

import (
"github.com/stretchr/testify/assert"
"testing"
)

func TestNumberSink(t *testing.T) {
testCase := []struct {
input []int
expect []int
}{
{
[]int{1,0,2,0,3,0,4,0,5,0},
[]int{1,2,3,4,5,0,0,0,0,0},
},
{
[]int{1,0,0,0,0},
[]int{1,0,0,0,0},
},
{
[]int{0,0,0,0,1},
[]int{1,0,0,0,0},
},
{
[]int{0,0,1,0,0},
[]int{1,0,0,0,0},
},
{
[]int{},
[]int{},
},
{
[]int{1},
[]int{1},
},
}
for _, c :=range testCase {
got := NumberSink(c.input)
assert.Equal(t, got, c.expect)
}
}

0 comments on commit 84431ec

Please sign in to comment.