2016-11-16 43 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

是。