Thank you for your help, everyone!
Took me about an hour to fully understand cfern's isPrime2 function, and have yet to understand the <a href = "http://cs.hubfs.net/forums/permalink/13544/13575/ShowThread.aspx#13575">Robin-Miller method</a>, <a href="/members/sharpdev.aspx">sharpdev</a> presented. But I'll definitely continue trying :). Thanks again for your help and this great community you make.
I've solved this problem too, and the biggest speed gain is to be found in the primality test.
Compare these two prime tests, for instance:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
//ye olde-fashioned primality test let isPrime n = {2L..int64 (sqrt (float n))} |> Seq.forall (fun d -> n%d <> 0L) //A faster test, using the fact that primes>3 are of the form 6k +/- 1 //It's also faster because it's a (tail recursive) loop. It doesn't need //to walk along a sequence iterator. //It's not as readable as the test above, but speed matters here. let isPrime2 = function | n when n<=1L -> false | 2L | 3L -> true | N when N &&& 1L = 0L || N%3L = 0L -> false | N -> let rec aux composite i num = if composite then false elif i*i > num then true else aux (num % i = 0L || num % (i+2L) = 0L) (i+6L) num aux false 5L N
I can bench these prime tests with the following problem 58 code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
let go primetest = let isPrimeN N = if primetest N then 1 else 0 //numCPrimes N = how many corners of a size N spiral are prime. (corner N*N omitted for obvious reasons) let numCPrimes N = ((isPrimeN (N*N-(N-1L))) + (isPrimeN (N*N-(2L*(N-1L)))) + (isPrimeN (N*N-(3L*(N-1L))))) let cornerPrimes ratio = let rec loop acc N = match acc with | acc when (( (float acc) / (-1. + 2.*(float N)) ) < ratio) -> (N,acc,( (float acc) / (-1. + 2.*(float N)) )) | _ -> loop (acc + numCPrimes (N+2L)) (N+2L) loop 3 3L let (euler058,acc,ratio) = cornerPrimes 0.1 printfn "Ratio --> %f | Primes --> %i |Side length --> %i" ratio acc euler058
Results:
1 2 3 4 5 6 7 8
> go isPrime;; Ratio --> 0.099998 | Primes --> 5248 |Side length --> 26241 Real: 00:00:09.394, CPU: 00:00:09.390, GC gen0: 2, gen1: 0, gen2: 0 val it : unit = () > go isPrime2;; Ratio --> 0.099998 | Primes --> 5248 |Side length --> 26241 Real: 00:00:00.391, CPU: 00:00:00.390, GC gen0: 0, gen1: 0, gen2: 0 val it : unit = ()
This demonstrates that the efficiency of the primality test is important here.
and the biggest speed gain is to be found in the primality test
You're right. With the following (simple) implementation of the Rabin Miller pseudo primality test speed is still increased.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
(* Rabin-Miller pseudo primality test*) let decompose n = let rec decompose' k r = if k % 2L = 0L then decompose' (k / 2L) (r + 1L) else (r,k) decompose' n 0L let rec powerMod n a q = if q = 0L then 1L else let (q',r') = (q / 2L, q % 2L) let a' = powerMod n ((a * a) % n) q' if r' = 0L then a' else (a * a') % n let oneOfEqualMinusOne n aq r = List.exists ((=) (n - 1L)) (List.scan (fun x _ -> (x * x) % n) aq [1L..(r - 1L)]) let rabinMiller a n = if n % 2L = 0L then false else let n' = n - 1L let (r,q) = decompose n' let aq = powerMod n a q if aq = 1L then true else oneOfEqualMinusOne n aq r // true primality if n < 2 152 302 898 747 let isPrime n = let l = [2L;3L;5L;7L;11L] if List.exists ((=) n) l then true else List.forall (fun p -> rabinMiller p n) l let rec pb58 n k = let k' = k + (int64 (List.length (List.filter isPrime [n*n - n+1L;n*n-2L*n+2L;n*n-3L*n+3L]))) if 10L*k' < 2L*n - 1L then n else pb58 (n+2L) k' printfn "solution : %i" (pb58 3L 0L)
use a sequence instead of an array in the is_prime function
for example
1 2 3 4 5 6 7 8 9 10 11 12
let is_prime n = seq{for i in 2..sqrt_int n -> i} |> Seq.exists (fun x -> n % x = 0) |> not let rec pb58 n k = let k' = k + List.length (List.filter is_prime [n*n - n+1;n*n-2*n+2;n*n-3*n+3]) if 10*k' < 2*n - 1 then n else pb58 (n+2) k' printfn "solution : %i" (pb58 3 0) // solution = 26241
Just some quickies:
- try "inline"ing the utiluty fn's like sqrt_int, diff2, etc.?
- calls to the O(n) List.length's stand out - use o(1) collection or pass in lengths?
- use higher-order fn's such as map/fold/reduce
- Looks like is_prime didn't get listed correctly - make sure it memoizes if the same # is likely to be queried again?
Topic tags
- f# × 3705
- websharper × 1897
- compiler × 286
- functional × 201
- ui next × 139
- c# × 121
- classes × 97
- web × 97
- .net × 84
- book × 84
- async × 76
- ui.next × 67
- bug × 54
- core × 49
- website × 49
- server × 45
- parallel × 43
- ui × 43
- enhancement × 41
- parsing × 41
- testing × 41
- trywebsharper × 41
- typescript × 37
- html × 35
- javascript × 35
- owin × 35
- asynchronous × 30
- monad × 28
- ocaml × 28
- tutorial × 27
- warp × 27
- haskell × 26
- sitelet × 25
- linq × 22
- workflows × 22
- wpf × 20
- fpish × 19
- introduction × 19
- silverlight × 19
- sitelets × 19
- monodevelop × 17
- rpc × 17
- suave × 17
- piglets × 16
- collections × 15
- feature request × 15
- jquery × 15
- templates × 15
- getting started × 14
- pipeline × 14
- kendoui × 13
- reactive × 12
- 4.1.0.171 × 11
- monads × 11
- opinion × 10
- 4.0.190.100-rc × 9
- deployment × 9
- fixed × 9
- formlets × 9
- in × 9
- json × 9
- plugin × 9
- proposal × 9
- scheme × 9
- solid × 9
- basics × 8
- concurrent × 8
- highcharts × 8
- how-to × 8
- python × 8
- 4.1.1.175 × 7
- complexity × 7
- documentation × 7
- visual studio × 7
- 4.1.2.178 × 6
- lisp × 6
- real-world × 6
- released in 4.0.192.103-rc × 6
- remoting × 6
- resources × 6
- scala × 6
- websharper ui.next × 6
- workshop × 6
- xaml × 6
- 4.0.193.110 × 5
- 4.2.3.236 × 5
- aspnetmvc × 5
- authentication × 5
- azure × 5
- bootstrap × 5
- conference × 5
- dsl × 5
- formlet × 5
- java × 5
- list × 5
- metaprogramming × 5
- ml × 5
- released in Zafir.4.0.188.91-beta10 × 5
- sql × 5
- visualstudio × 5
- websharper.forms × 5
- zafir × 5
- 4.0.192.106 × 4
- 4.0.195.127 × 4
- 4.1.0.38 × 4
- 4.2.1.86 × 4
- 4.2.6.118 × 4
- css × 4
- example × 4
- extensions × 4
- fsi × 4
- fsx × 4
- html5 × 4
- jqueryui × 4
- lift × 4
- reflection × 4
- remote × 4
- rest × 4
- spa × 4
- teaching × 4
- template × 4
- websocket × 4
- wontfix × 4
- 4.0.196.147 × 3
- 4.1.0.34 × 3
- 4.1.6.207 × 3
- 4.2.1.223-beta × 3
- 4.2.11.258 × 3
- 4.2.4.114 × 3
- 4.2.4.247 × 3
- 4.2.5.115 × 3
- 4.2.6.253 × 3
- 4.2.9.256 × 3
- ajax × 3
- alt.net × 3
- aml × 3
- asp.net mvc × 3
- canvas × 3
- cloudsharper × 3
- compilation × 3
- database × 3
- erlang × 3
- events × 3
- extension × 3
- file upload × 3
- forums × 3
- inline × 3
- issue × 3
- kendo × 3
- macro × 3
- mono × 3
- msbuild × 3
- mvc × 3
- pattern × 3
- piglet × 3
- released in Zafir.4.0.187.90-beta10 × 3
- svg × 3
- type provider × 3
- view × 3
- 4.1.1.64 × 2
- 4.1.5.203 × 2
- 4.1.7.232 × 2
- 4.2.10.257 × 2
- 4.2.3.111 × 2
- 4.2.5.249 × 2
- android × 2
- asp.net × 2
- beginner × 2
- blog × 2
- chart × 2
- client × 2
- client server app × 2
- clojure × 2
- computation expressions × 2
- constructor × 2
- corporate × 2
- courses × 2
- cufp × 2
- d3 × 2
- debugging × 2
- direct × 2
- discriminated union × 2
- docs × 2
- elm × 2
- endpoint × 2
- endpoints × 2
- enterprise × 2
- entity framework × 2
- event × 2
- f# interactive × 2
- fable × 2
- flowlet × 2
- formdata × 2
- forms × 2
- fsc × 2
- google maps × 2
- hosting × 2
- http × 2
- https × 2
- iis 8.0 × 2
- install × 2
- interactive × 2
- interface × 2
- iphone × 2
- iteratee × 2
- jobs × 2
- jquery mobile × 2
- keynote × 2
- lens × 2
- lenses × 2
- linux × 2
- listmodel × 2
- mac × 2
- numeric × 2
- oauth × 2
- obfuscation × 2
- offline × 2
- oop × 2
- osx × 2
- packaging × 2
- pattern matching × 2
- performance × 2
- pipelines × 2
- q&a × 2
- quotation × 2
- reference × 2
- released in Zafir.4.0.185.88-beta10 × 2
- rx × 2
- script × 2
- security × 2
- self host × 2
- seq × 2
- sockets × 2
- stm × 2
- tcp × 2
- trie × 2
- tutorials × 2
- type × 2
- url × 2
- var × 2
- websharper.charting × 2
- websharper4 × 2
- websockets × 2
- wig × 2
- xna × 2
- zh × 2
- .net interop × 1
- 2012 × 1
- 4.0.194.126 × 1
- 4.1.3.184 × 1
- 4.1.4.189 × 1
- 4.2.0.214-beta × 1
- 4.2.12.259 × 1
- 4.2.2.231-beta × 1
- 4.2.8.255 × 1
- Canvas Sample Example × 1
- DynamicStyle Animated Style × 1
- Fixed in 4.0.190.100-rc × 1
- Released in Zafir.UI.Next.4.0.169.79-beta10 × 1
- SvgDynamicAttribute × 1
- WebComponent × 1
- abstract class × 1
- accumulator × 1
- active pattern × 1
- actor × 1
- addin × 1
- agents × 1
- aggregation × 1
- agile × 1
- alter session × 1
- animation × 1
- anonymous object × 1
- apache × 1
- api × 1
- appcelerator × 1
- architecture × 1
- array × 1
- arrays × 1
- asp.net 4.5 × 1
- asp.net core × 1
- asp.net integration × 1
- asp.net mvc 4 × 1
- asp.net web api × 1
- aspnet × 1
- ast × 1
- attributes × 1
- authorization × 1
- b-tree × 1
- back button × 1
- badimageformatexception × 1
- bash script × 1
- batching × 1
- binding-vars × 1
- bistro × 1
- body × 1
- bundle × 1
- camtasia studio × 1
- cas protocol × 1
- charts × 1
- clarity × 1
- class × 1
- cli × 1
- clipboard × 1
- clojurescript × 1
- closures × 1
- cloud × 1
- cms × 1
- coding diacritics × 1
- color highlighting × 1
- color zones × 1
- combinator × 1
- combinators × 1
- compile × 1
- compile code on server × 1
- config × 1
- confirm × 1
- content × 1
- context × 1
- context.usersession × 1
- continuation-passing style × 1
- coords × 1
- cordova × 1
- cors × 1
- coursera × 1
- cross-domain × 1
- csla × 1
- current_schema × 1
- custom content × 1
- data × 1
- data grid × 1
- datetime × 1
- debug × 1
- declarative × 1
- delete × 1
- devexpress × 1
- dhtmlx × 1
- dictionary × 1
- directattribute × 1
- disqus × 1
- distance × 1
- do binding × 1
- doc elt ui.next upgrade × 1
- docker × 1
- dojo × 1
- dol × 1
- dom × 1
- domain × 1
- du × 1
- duf-101 × 1
- dynamic × 1
- eastern language × 1
- eclipse × 1
- edsl × 1
- em algorithm × 1
- emacs × 1
- emotion × 1
- enums × 1
- error × 1
- etw × 1
- euclidean × 1
- eventhandlerlist × 1
- examples × 1
- ext js × 1
- extension methods × 1
- extra × 1
- facet pattern × 1
- failed to translate × 1
- fake × 1
- fantomas × 1
- fear × 1
- float × 1
- form × 1
- form-data × 1
- forum × 1
- fp × 1
- frank × 1
- fsdoc × 1
- fsharp × 1
- fsharp.core × 1
- fsharp.powerpack × 1
- fsharpx × 1
- fsunit × 1
- function × 1
- functional style × 1
- game × 1
- games × 1
- gc × 1
- generic × 1
- geometry × 1
- getlastwin32error × 1
- getting-started × 1
- google × 1
- google.maps × 1
- grid × 1
- group × 1
- guide × 1
- hash × 1
- headers × 1
- hello world example × 1
- heroku × 1
- highchart × 1
- history × 1
- how to × 1
- html-templating × 1
- http405 × 1
- httpcontext × 1
- hubfs × 1
- i18n × 1
- ie 8 × 1
- if-doc × 1
- iis × 1
- image × 1
- images × 1
- inheritance × 1
- initialize × 1
- input × 1
- install "visual studio" × 1
- installer × 1
- int64 × 1
- interfaces × 1
- internet explorer × 1
- interop × 1
- interpreter × 1
- io × 1
- iobservable × 1
- ios × 1
- iot × 1
- ipad × 1
- isomorphic × 1
- javascript optimization × 1
- javascript semanticui resources × 1
- jquery-plugin × 1
- jquery-ui × 1
- jquery-ui-datepicker × 1
- js × 1
- kendo datasource × 1
- kendochart × 1
- kendoui compiler × 1
- knockout × 1
- l10n × 1
- learning × 1
- library × 1
- libs × 1
- license × 1
- licensing × 1
- lineserieszonescfg × 1
- local setting × 1
- localization × 1
- logging × 1
- loop × 1
- macros × 1
- mailboxprocessor × 1
- mapping × 1
- maps × 1
- markerclusterer × 1
- markup × 1
- marshal × 1
- math × 1
- mathjax × 1
- message × 1
- message passing × 1
- message-passing × 1
- meta × 1
- metro style × 1
- micro orm × 1
- minimum-requirements × 1
- mix × 1
- mobile installation × 1
- mod_mono × 1
- modal × 1
- module × 1
- mouseevent × 1
- mouseposition × 1
- multidimensional × 1
- multiline × 1
- multithreading × 1
- mysql × 1
- mysqlclient × 1
- nancy × 1
- native × 1
- nested × 1
- nested loops × 1
- node × 1
- nunit × 1
- object relation mapper × 1
- object-oriented × 1
- om × 1
- onboarding × 1
- onclick × 1
- optimization × 1
- option × 1
- orm × 1
- os x × 1
- output-path × 1
- override × 1
- paper × 1
- parameter × 1
- persistence × 1
- persistent data structure × 1
- phonegap × 1
- pola × 1
- post × 1
- powerpack × 1
- prefix tree × 1
- principle of least authority × 1
- privacy × 1
- private × 1
- profile × 1
- programming × 1
- project × 1
- project euler × 1
- projekt_feladat × 1
- protected × 1
- provider × 1
- proxy × 1
- ptvs × 1
- public × 1
- pure f# × 1
- purescript × 1
- qna × 1
- quant × 1
- query sitelet × 1
- question × 1
- quotations × 1
- range × 1
- raphael × 1
- razor × 1
- rc × 1
- reactjs × 1
- real-time × 1
- ref × 1
- region × 1
- released in 4.0.190.100-rc × 1
- reporting × 1
- responsive design × 1
- rest api × 1
- rest sitelet × 1
- restful × 1
- round table × 1
- router × 1
- routing × 1
- rpc reverseproxy × 1
- runtime × 1
- sales × 1
- sample × 1
- sampleapp × 1
- scriptcs × 1
- scripting × 1
- search × 1
- self hosted × 1
- semanticui × 1
- sequence × 1
- serialisation × 1
- service × 1
- session-state × 1
- sharepoint × 1
- signals × 1
- sitelet website × 1
- sitelet.protect × 1
- sitlets × 1
- slickgrid × 1
- source code × 1
- sqlentityconnection × 1
- ssl × 1
- standards × 1
- static content × 1
- stickynotes × 1
- streamreader × 1
- stress × 1
- strong name × 1
- structures × 1
- submitbutton × 1
- subscribe × 1
- svg example html5 websharper.ui.next × 1
- sweetalert × 1
- system.datetime × 1
- system.reflection.targetinvocationexception × 1
- table storage × 1
- targets × 1
- tdd × 1
- templates ui.next × 1
- templating × 1
- text parsing × 1
- three.js × 1
- time travel × 1
- tls × 1
- tooltip × 1
- tracing × 1
- tsunamiide × 1
- turkish × 1
- twitter-bootstrap × 1
- type erasure × 1
- type inference × 1
- type providers × 1
- type-providers × 1
- typeprovider × 1
- ui next forms × 1
- ui-next × 1
- ui.next jqueryui × 1
- ui.next charting × 1
- ui.next formlets × 1
- ui.next forms × 1
- ui.next suave visualstudio × 1
- ui.next templating × 1
- unicode × 1
- unittest client × 1
- upload × 1
- usersession × 1
- validation × 1
- vb × 1
- vb.net × 1
- vector × 1
- view.map × 1
- visal studio × 1
- visual f# × 1
- visual studio 11 × 1
- visual studio 2012 × 1
- visual studio shell × 1
- vs2017 compiler zafir × 1
- vsix × 1
- web api × 1
- web-scraping × 1
- webapi × 1
- webcomponents × 1
- webforms × 1
- webgl × 1
- webrtc × 1
- webshaper × 1
- websharper async × 1
- websharper codemirror × 1
- websharper f# google × 1
- websharper forms × 1
- websharper reactive × 1
- websharper rpc × 1
- websharper sitelets routing × 1
- websharper warp × 1
- websharper-interface-generator × 1
- websharper.chartsjs × 1
- websharper.com × 1
- websharper.exe × 1
- websharper.owin × 1
- websharper.ui.next × 1
- websharper.ui.next jquery × 1
- websockets iis × 1
- why-websharper × 1
- windows 7 × 1
- windows 8 × 1
- windows-phone × 1
- winrt × 1
- www.grabbitmedia.com × 1
- xamarin × 1
- xml × 1
- yeoman × 1
- yield × 1
- zafir beta × 1
- zafir websharper4 × 1
- zarovizsga × 1
![]() |
Copyright (c) 2011-2012 IntelliFactory. All rights reserved. Home | Products | Consulting | Trainings | Blogs | Jobs | Contact Us | Terms of Use | Privacy Policy | Cookie Policy |
Built with WebSharper |
Hello everyone!
This is my first post, so please be kind :).
As many people here do, I try to develop my skills in F# by solving Project Euler problems.
And I have a question about <a href=http://projecteuler.net/index.php?section=problems&id=58> Problem 58 </a> I wrote this code to solve it, and it successfully does the solving. But it runs about 2 full minutes on a modern computer. Could anyone please show me the slowest parts of the code? And maybe ways to improve them? Here is the actual code: <code lang=fsharp> #light let sqrt_int n = n |> float |> sqrt |> int64 let is_prime n = if n < 2L then false else [|2L .. sqrt_int n|] |> Array.exists (fun x -> n % x = 0L) |> not let diff2 (l1, l2) = ((l1 |> float) / (l2 |> float)) * 100. let numOfPrimesInSpiral ratio = let rec loop incBy acc count prev primes both currRatio = match currRatio with //We've finished the current loop of the spiral and current ratio is now below // target ratio -> finish. | _ when currRatio < ratio && count = 0L -> (incBy+1L, ratio) | _ -> match count with | nil when nil = 0L -> //start a new loop of spiral let i = prev + (incBy + 2L) if is_prime i then let prLen = primes |> List.length let bothLen = both |> List.length let r = ((prLen)+1, (bothLen)+1) |> diff2 loop (incBy+2L) (acc+i) 3L i (i::primes) (i::both) r else let prLen = primes |> List.length let bothLen = both |> List.length let r = ((prLen), (bothLen)+1) |> diff2 loop (incBy+2L) (acc+i) 3L i primes (i::both) r | _ -> //cotinue the current loop let i = prev + incBy if is_prime i then let prLen = primes |> List.length let bothLen = both |> List.length let r = ((prLen)+1, (bothLen)+1) |> diff2 loop incBy (acc+i) (count-1L) i (i::primes) (i::both) r else let prLen = primes |> List.length let bothLen = both |> List.length let r = ((prLen), (bothLen)+1) |> diff2 loop incBy (acc+i) (count-1L) i (primes) (i::both) r match ratio with | hundred when hundred = 100. -> (1L, 100.) | over when over > 100. -> failwith "ratio cannot be larger than 100%" | _ -> loop 2L 1L 4L 1L [] [1L] 0. let te = 10. printfn "test on %f is %A" te (numOfPrimesInSpiral te) </code> Thanks in advance! PS: I tried to get the indents right in the code block, but failed to do so even after reading <a href="/forums/post/12824.aspx">this helpful post</a>