2016-11-16 88 views
0

背景:我試圖實現一個邏輯,它可以找到最小的正數,它可以被1到20之間的所有數字整除。我實現了一個順序版本並得到了答案爲232792560.更正我的公寓的實施

問:當我嘗試建立在這個問題上的一些併發(見的代碼取消註釋塊),它不運行,但從來沒有顯示有任何結果。你們中的任何一個人能指導我去哪裏出錯?

注意:我非常新golang;而我知道,因爲沒有保證,我將有最小的正數作爲第一個結果,這不是併發最好的問題。不過,我出於好奇,試了一下。

package main 

    import(
     "fmt" 
    ) 

    func divide(num int) bool { 
     for i := 1; i <= 20; i++ { 
      if num % i != 0 { 
       return false 
      } 
     } 
     return true 
    } 

    func main() { 
     num:=0 
     //simple function 
     /*for { 
      num++; 
      result := divide(num) 
       if result { 
        fmt.Println("Smallest number is: ", num) 
        break 
       } 
      }*/ 


     //go-routine 
     //go-routine 
    var wg sync.WaitGroup 
    for { 
     num++; 
     wg.Add(1) 
     go func(x int) { 
      result := divide(x) 
      if result { 
       fmt.Println("Smallest number is: ", x) 
       defer wg.Done() 
      } 

     }(num) 

    } 
    wg.Wait() 
    fmt.Println("End.") 

} 
+1

希望這也很明顯,蠻力的方法是不是解決問題的最好方法,同時或以其他方式。 – Iridium

回答

1

它沒有意義發動夠程的數量不受限制 - 將執行比非併發的解決方案更糟糕。您可以嘗試使用「工作人員池」模式並對計算進行批處理。

package main 

import (
    "fmt" 
    "runtime" 
) 

func divide(num int) bool { 
    for i := 1; i <= 20; i++ { 
     if num%i != 0 { 
      return false 
     } 
    } 
    return true 
} 

const step = 100000 

func main() { 
    result := make(chan int) 
    jobs := make(chan int) 
    for w := 0; w < runtime.NumCPU(); w++ { 
     go func() { 
      for n := range jobs { 
       for i := n; i < n+step; i++ { 
        if divide(i) { 
         result <- i 
        } 
       } 
      } 
     }() 
    } 
    num := 1 
    for { 
     select { 
     case jobs <- num: 
      num += step 
     case x := <-result: 
      fmt.Println("Smallest number is:", x) 
      return 
     } 
    } 
} 
1

您的問題的另一種方法是過濾器。我們的想法是鏈渠道一堆夠程的,讓他們過濾,沒有通過一些測試所有值。你的情況要篩選不可由一些數整除的數字。這是它的外觀:

package main 

import (
    "fmt" 
) 

func main() { 
    in := make(chan int) 
    tmp := in 
    // Create filter-goroutines 
    for i := 1; i <= 20; i++ { 
     tmp = makeDivisor(i, tmp) 
    } 

    running := true 

    // Now feed in all the numbers... 
    for i := 1; running; i++ { 
     select { 

     // Check if a number passed all filters. 
     case k := <-tmp: 
      fmt.Printf("Answer is %d\n", k) 
      close(in) 
      running = false 

     // Otherwise feed in the next. 
     case in <- i: 
     } 
    } 

} 

func makeDivisor(n int, c chan int) chan int { 
    cc := make(chan int) 
    go func() { 
     for i := range c { 
      if i%n == 0 { 
       cc <- i 
      } 
     } 
     close(cc) 
    }() 
    return cc 
} 

這對playground。 (請注意,遊樂場不會與20個過濾器的工作,但嘗試過本地)

注意第一個過濾器有更多的工作比的那些進一步進入鏈做。你可以推出更多的第一過濾器來解決這個問題,雖然整數除法是相當快,這件事可能是由通道通信目前的限制。

是否行得通?

答案是232792560

是。