Guest User

Covering natural numbers with geometric progressions

a guest
Jul 16th, 2019
237
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 4.08 KB | None | 0 0
  1. /*
  2.  Helper program for https://oeis.org/A309095
  3.  Find the smallest number of geometric progressions that cover the numbers 1, 2, ... N
  4.  https://math.stackexchange.com/questions/1385991/what-is-known-about-the-minimal-number-fn-of-geometric-progressions-needed-t?lq=1
  5.  
  6.  Dmitry Kamenetsky, 17th July 2019
  7. */
  8.  
  9.  
  10. import java.util.*;
  11.  
  12.  
  13. public class CoveringGP
  14. {
  15.     static int N;
  16.     static List<GP> GPs = new ArrayList<GP>();
  17.  
  18.     public static void main(String[] args) 
  19.     {
  20.         if (args.length!=1)
  21.         {
  22.             System.out.println("usage: java CoveringGP N");
  23.             System.out.println("Finds the smallest number of geometric progressions that cover the numbers 1, 2, ..., N");
  24.             System.out.println("Only prints progressions with 3 or more terms, the remaining numbers can be covered with one progression for each two numbers");
  25.             System.exit(0);
  26.         }
  27.         N=Integer.parseInt(args[0]);
  28.  
  29.  
  30.         generateGPSrational();     
  31.         solve();
  32.     }
  33.  
  34.     public static void generateGPSrational()
  35.     {
  36.         //first,second
  37.         boolean[][] seen=new boolean[N+1][N+1];
  38.  
  39.         System.out.println("progressions with 3 or more terms:");
  40.  
  41.         for (int i=1; i<=N; i++)
  42.         {
  43.             for (int k=i+1; k<=N; k++)
  44.             {
  45.                 if (seen[i][k]) continue;
  46.  
  47.  
  48.                 int div=getMinDivisor(i,k);
  49.                 if (div==-1) continue;
  50.                 int mult=k/(i/div);
  51.  
  52.                 int cur=i;
  53.                 GP gp=new GP();
  54.  
  55.                 while(true)
  56.                 {
  57.                     gp.a.add(cur);
  58.  
  59.                     if (cur%div!=0) break;
  60.                     cur/=div;
  61.                     cur*=mult;
  62.                     if (cur>N) break;
  63.                 }
  64.  
  65.                 if (gp.a.size()>=3)
  66.                 {
  67.                     for (int a : gp.a) System.out.print(a+" ");
  68.                     System.out.println();
  69.  
  70.                     GPs.add(gp);
  71.  
  72.                     //update seen
  73.                     for (int p=0; p<gp.a.size(); p++)
  74.                         for (int q=p+1; q<gp.a.size(); q++)
  75.                             seen[gp.a.get(p)][gp.a.get(q)]=true;
  76.                 }
  77.             }
  78.         }
  79.  
  80.         System.out.println("total number of progressions: "+GPs.size()+"\n");
  81.     }
  82.  
  83.     //b>a
  84.     public static int getMinDivisor(int a, int b)
  85.     {
  86.         for (int i=1; i<=Math.min(a,b); i++)
  87.             if (a%i==0 && b%i==0 && b%(a/i)==0) return i;
  88.         return -1;
  89.     }
  90.  
  91.    
  92.     public static void solve()
  93.     {
  94.     int n=GPs.size();
  95.     int maxChanges=5;
  96.     int bestScore=Integer.MAX_VALUE;
  97.  
  98.     if (n==0)
  99.     {
  100.         System.out.println("progressions needed: "+(N+1)/2);
  101.         return;
  102.     }
  103.    
  104.    
  105.     boolean[] bestA=new boolean[n];
  106.     for (int i=0; i<n; i++) bestA[i]=(Math.random()<0.5);
  107.    
  108.     boolean[] a=new boolean[n];
  109.    
  110.     while(true)
  111.     {
  112.       for (int i=0; i<n; i++) a[i]=bestA[i];
  113.      
  114.       int changes=(int)(Math.random()*maxChanges+1);
  115.       for (int i=0; i<changes; i++)
  116.       {
  117.         int pos=(int)(Math.random()*n);
  118.         a[pos]=!a[pos];
  119.       }
  120.      
  121.       int score=score(a);
  122.       if (score<=bestScore)
  123.       {
  124.         if (score<bestScore && score<=N/2)
  125.         {
  126.           System.out.println("progressions needed: "+score);
  127.           print(a);
  128.           System.out.println("progressions needed: "+score);
  129.           System.out.println();
  130.         }
  131.         bestScore=score;
  132.        
  133.         for (int i=0; i<n; i++) bestA[i]=a[i];
  134.       }
  135.     }
  136.     }
  137.    
  138.    
  139.     //computes number of sets needed to cover all numbers
  140.     public static int score(boolean[] a)
  141.     {    
  142.     Set<Integer> covered=new HashSet<Integer>();    //integers that are covered
  143.    
  144.     int sets=0;
  145.     for (int i=0; i<GPs.size(); i++)
  146.       if (a[i])
  147.       {
  148.         sets++;
  149.         for (int k : GPs.get(i).a) covered.add(k);
  150.       }
  151.    
  152.     int missing=N-covered.size();
  153.     int extraSets=(missing+1)/2;      //extra sets can cover up to 2 numbers each
  154.    
  155.     return sets+extraSets;
  156.   }
  157.  
  158.  
  159.   public static void print(boolean[] a)
  160.   {
  161.     for (int i=0; i<GPs.size(); i++)
  162.     {
  163.       if (a[i])
  164.       {
  165.         GPs.get(i).print();
  166.         System.out.print(", ");
  167.       }
  168.     }
  169.     System.out.println();
  170.   }
  171.  
  172.    
  173.  
  174.     static class GP
  175.     {
  176.         List<Integer> a;
  177.         public GP()
  178.         {
  179.             a=new ArrayList<Integer>();
  180.         }
  181.        
  182.         void print()
  183.         {
  184.       System.out.print("(");
  185.       for (int i=0; i<a.size(); i++)
  186.       {
  187.         System.out.print(a.get(i));
  188.         if (i<a.size()-1) System.out.print(",");
  189.       }
  190.       System.out.print(")");
  191.         }
  192.     }
  193. }
Advertisement
Add Comment
Please, Sign In to add comment