{"id":1068,"date":"2014-07-27T18:57:02","date_gmt":"2014-07-28T01:57:02","guid":{"rendered":"https:\/\/dubinko.info\/blog\/?p=1068"},"modified":"2014-07-27T18:57:02","modified_gmt":"2014-07-28T01:57:02","slug":"prime-number-sieve-in-scala","status":"publish","type":"post","link":"https:\/\/dubinko.info\/blog\/2014\/07\/prime-number-sieve-in-scala\/","title":{"rendered":"Prime Number sieve in Scala"},"content":{"rendered":"<p>There are a number of sieve algorithms that can be used to list\u00c2\u00a0prime numbers up to a certain value. \u00c2\u00a0I came up with this implementation\u00c2\u00a0in Scala. I rather like it, as it makes no use of division, modulus, and only one (explicit) multiplication.<\/p>\n<p>Despite being in Scala, it&#8217;s not in a functional style. It uses the awesome\u00c2\u00a0mutable BitSet data structure which is very efficient in space and time. It is intrinsically ordered and it allows an iterator, which makes jumping to the next known prime easy. Constructing a BitSet from a for comprehension is also easy with breakOut.<\/p>\n<p>The basic approach is the start with a large BitSet filled will all odd numbers (and 2), then iterate through the BitSet, constructing a new BitSet containing numbers to be crossed off, which is easily done with the &amp;~= (and-not) reassignment method. Since this is a logical bitwise operation, it&#8217;s blazing fast. This code takes longer to compile than run\u00c2\u00a0on my oldish MacBook Air.<\/p>\n<pre>\r\nimport scala.collection.mutable.BitSet\r\nimport scala.collection.breakOut<\/pre>\n<pre>println(new java.util.Date())\r\nval top = 200000<\/pre>\n<pre>val sieve = BitSet(2)\r\nsieve |= (3 to top by 2).map(identity)(breakOut)<\/pre>\n<pre>val iter = sieve.iteratorFrom(3)\r\nwhile(iter.hasNext) {\r\n val n = iter.next\r\n sieve &amp;~= (2*n to top by n).map(identity)(breakOut)\r\n}<\/pre>\n<pre>println(sieve.toIndexedSeq(10000)) \/\/ 0-based\r\nprintln(new java.util.Date())<\/pre>\n<p>As written here, it&#8217;s a solution to <a href=\"https:\/\/projecteuler.net\/problem=7\">Euler #7<\/a>, but it could be made even faster for more general use.<\/p>\n<p>For example<\/p>\n<ul>\n<li>I used a hard-coded top value (which is fine when you need to locate all primes up to \u00c2\u00a0<em>n<\/em>). For finding the <em>n<\/em>th prime, though, the top limit could <a href=\"http:\/\/en.wikipedia.org\/wiki\/Prime-counting_function\">be calculated<\/a><\/li>\n<li>I could stop iterating at sqrt(top)<\/li>\n<li>I could construct the removal BitSet\u00c2\u00a0starting\u00c2\u00a0at n*n rather than n*2<\/li>\n<\/ul>\n<p>I suspect that spending some time in the profiler could make this even faster. So take this as an example of the power of Scala, and a reminder that sometimes a non-FP solution can be valid too. Does anyone have a FP equivalent to this that doesn&#8217;t make my head hurt? :-)<\/p>\n<p>-m<\/p>\n","protected":false},"excerpt":{"rendered":"<p>There are a number of sieve algorithms that can be used to list\u00c2\u00a0prime numbers up to a certain value. \u00c2\u00a0I came up with this implementation\u00c2\u00a0in Scala. I rather like it, as it makes no use of division, modulus, and only one (explicit) multiplication. Despite being in Scala, it&#8217;s not in a functional style. It uses&#8230;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":false,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2}},"categories":[27,22],"tags":[1143,1177,248,1141,1140,1142],"class_list":["post-1068","post","type-post","status-publish","format-standard","hentry","category-languages","category-software","tag-bitset","tag-math","tag-optimization","tag-prime","tag-scala","tag-sieve"],"aioseo_notices":[],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/p8eo8l-he","_links":{"self":[{"href":"https:\/\/dubinko.info\/blog\/wp-json\/wp\/v2\/posts\/1068","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/dubinko.info\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/dubinko.info\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/dubinko.info\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/dubinko.info\/blog\/wp-json\/wp\/v2\/comments?post=1068"}],"version-history":[{"count":1,"href":"https:\/\/dubinko.info\/blog\/wp-json\/wp\/v2\/posts\/1068\/revisions"}],"predecessor-version":[{"id":1069,"href":"https:\/\/dubinko.info\/blog\/wp-json\/wp\/v2\/posts\/1068\/revisions\/1069"}],"wp:attachment":[{"href":"https:\/\/dubinko.info\/blog\/wp-json\/wp\/v2\/media?parent=1068"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/dubinko.info\/blog\/wp-json\/wp\/v2\/categories?post=1068"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/dubinko.info\/blog\/wp-json\/wp\/v2\/tags?post=1068"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}