NuGet isn’t going away, so the best we can do is try to reduce the friction imposed upon us. Chewie was a project created by Eric Ridgeway in June 2011 with the goal of bringing Bundler like functionality to NuGet. While this solution has a number of shortcommings listed in my last NuGet post, I believe it is a much better solution that the vanilla NuGet experience. I rewrote Chewie based on many of Bundler’s features, and have come to a point where I believe it is ready for a public preview.
chewieinit-pathpackageschewieinstallNinjectchewieinstall# installs all dependencies in the .NugetFilechewieoutdated# determines if any packages are outdated based on their version requirementschewieupdatechewieuninstallchewieconvert
In the last article on prototypal inheritance using Archetype, I showed how to construct a delegation chain and simulate JavaScript’s prototypal inheritance for .NET languages. If you haven’t looked at that post, I highly recommend reading it through as I am going to skip over a lot of the theory I covered previously. Today I am taking delegation in .NET a step further. If you aren’t familiar with mixins and ruby modules, I would also recommend looking into them as what I am showing here is directly inspired by them.
When looking at prototypal inheritance for .NET, we had a very simple delegation chain. With module support we need to ammend how we evaluate and interpret expressions being called on our objects. Does the current object support the operation? Can it respond? If not, we need to loop through the prototypes (modules/mixins) that have been attached to this instance; however, as with most things in life, there is a catch. We need to process them last to first and at each level we need to start the evaluation all over again. Why last first?
When we declare a module/mixin for our class, it is taking precededence over the modules that have already been imported. This mimics the way that Ruby works. Defining a property or method that already exists redefines that member.
Revisiting the DelegatingObject (formerly PrototypalObject), I have added a new backing list to replace the single prototype from the earlier version. All existing tests and code continue to work just fine with these minimal changes. The big change is the call to creating the DynamicMetaObject with the ModuleMetaObjectctor. We are passing a collection of prototypes/modules which will be evaluated by the ModuleMetaObject which may contain many more sets of modules and delegation chains.
Instead of executing a preorder traversal of the module chains, we are routing all binding calls to a new method ApplyBinding which isolates all of the resolution logic to a single method. We have an additional constraint this time in that we are binding the expression to delegation chains that may fail (whereas before we had only a single chain that could fail). When this binding failure occurs, an expression with a NodeType of ExpressionType.Throw is returned and we need to ignore these failed chains. I am also able to leverage Func<,>, Func<,,>, and closures to capture the binding calls and context arguments which makes every override an easy call to ApplyBinding.
There is one operation that has a custom implementation. The BindConvert call passes a lamdba expression which calls the Convert utility method. Casting is .NET has some interesting nuances that have to be taken into account that would break when doing the module resolution if it were done just like everything else.
One great thing about this implementation is that we can replicate prototypal inheritance completely. We just need to make sure that each module we create only has a single base module all the way through the chain.
With these two classes now in place, it is time to start having some fun. While there are many fun ways we can leverage the DelegatingObject to mix in behavior, today I am going to focus on one very specific usage.
Invariably, when talking about module support in .NET, one of the most common requests you will here people talk about is to have a INotifyPropertyChanged module. While this can now be easily done, we have an added benefit from the way that ModuleMetaObject handles casting. We can pass around our model object and it can be cast as INotifyPropertyChanged without the need to generate a runtime proxy. The cast will actually dig through the module hierarchy, find that we have a module which provides the interface, and return that object.
First, let’s create a utility interface and module that will help us out and abstract some boilerplate code.
One thing you may notice is that I did not use the CallerMemberName attribute available in .NET 4.5. When using modules, the caller name will not be the originating caller you expect. Since we are building expression trees to call the members at runtime, you cannot rely on this new feature.
With a module in place, we can now create a model which can have the functionality weaved in:
The implementation is pretty simple. The thing to remember is that in order for the module chain to trigger, whether you are in the object or acting on the model object, the invocation must take place on a dynamic object. I have provided a simple property This which casts the model object to dynamic allowing us to access the latebound method calls.
There are a few different ways we can work with this object now:
123456789101112131415161718192021222324
publicvoidUsingModelObjectAsDynamic(){dynamicperson=newPerson();// The cast to the interface will work returning the inner moduleINotifyPropertyChangesinpc=person;inpc.PropertyChanged+=(sender,args)=>Console.WriteLine("The field {0} has changed.",args.PropertyName);inpc.PropertyChanging+=(sender,args)=>Console.WriteLine("The field {0} is changing.",args.PropertyName);// We have full IntelliSense when working with inpc,// but now accessing person.Name looses IntelliSenseperson.Name="Inigo Montoya";// trigger the events}publicvoidUsingModelObjectAsStronglyTyped(){Personperson=newPerson();// Casting first to dynamic triggers the DelegatingObject's casting systemINotifyPropertyChangesinpc=(dynamic)person;inpc.PropertyChanged+=(sender,args)=>Console.WriteLine("The field {0} has changed.",args.PropertyName);inpc.PropertyChanging+=(sender,args)=>Console.WriteLine("The field {0} is changing.",args.PropertyName);// We have full IntelliSense when working with person.person.Name="Inigo Montoya";// trigger the events}
Sometimes, we may want to handle accessing the interface provided by a module. Again leveraging the dynamic casting, we can create a new property which will provide us access to the interface. I have also created a new Age property which takes advantage of this feature and now gives us IntelliSense when acting on the INotifyPropertyChanges feature.
We can also leverage this property to provide external access to our mixed in behavior:
12345678910
publicvoidUsingModelWithProxyCastingProperty(){Personperson=newPerson();// The cast property to give us IntelliSenseperson.Inpc.PropertyChanged+=(sender,args)=>Console.WriteLine("The field {0} has changed.",args.PropertyName);person.Inpc.PropertyChanging+=(sender,args)=>Console.WriteLine("The field {0} is changing.",args.PropertyName);// We also still have IntelliSense on Nameperson.Name="Inigo Montoya";// trigger the events}
So far, each model has received its own instance of a module, but that is by no means the only usage pattern. Object’s can share modules and behavior:
12345678910111213
publicvoidShareModulesToShareBehavior(){varmodule=newNotifyPropertyChangesModule();module.PropertyChanged+=(sender,args)=>Console.WriteLine("The field {0} has changed.",args.PropertyName);module.PropertyChanging+=(sender,args)=>Console.WriteLine("The field {0} is changing.",args.PropertyName);Personinigo=newPerson(module){Name="Inigo"};Personian=newPerson(module){Name="Ian"};// Four events triggered by setting the names, 2x Changed, 2x Changinginigo.Age=35;ian.Age=30;// The module is now acting somewhat like a message channel in a message broker}
This barely scratches the surface of what is possible, but hopefully it gives you a taste.
Another simple pattern you can apply is adding an ExpandoObject to the beginning of your module chain (thus it is the last resolved). This will give you a fallback behavior of the Expando should all else fail. You can also create a system to handle an analog to method_missing by overriding the TryXyz members you get when deriving from DelegatingObject (via DynamicObject). I playing around with a sample implementation right now which will also delegate to static members.
If you find this interesting or have ideas for other modules, I’d love to hear about them.
NuGet is the new (well, relatively new) hotness. Everyone loves NuGet. I am even guilty of extolling some of its virtues. I am not going to talk about the things which NuGet does well as they have been documented over and over again, and I don’t really have anything to add to those lists of awesome features. I can’t, however, advocate the way the owners of NuGet have taken the product.
Microsoft, along with most of the industry, went from using build domain specific languages (DSL) to drowning in XML. MSBuild, Ant, NAnt, XBuild, etc are all anathemas to our profession. Don’t get me wrong, they served their purpose, but we have to learn from those mistakes and move toward build systems based on coded build scripts using tools like Rake and Albacore, jake, and psake.
Leveraging existing programming languages, we can utilize their capabilities in creating DSLs to run our builds. Funny as this is, we have now come full circle, but with a better understanding of what a build should be.
Why bring this up? This applies directly to NuGet’s exhaustive use of XML. In addition, we have NuGet’s incredibly limited command-line outside of Visual Studio, and the choices to disempower users with unneeded hand holding. There is an incredible focus to force users to manage their dependencies inside of Visual Studio with a number of features, such as the PowerShell tool scripts, only working when you have the solution loaded.
Ruby
Ruby has had a package management system, gems, and a dependency bundling tool, bundler, for years. Gem specs are ruby code veiled in a thin DSL. You can see examples in the rspec gemspec and Albacore gemspec . They were made simple, leveraging the language and incredibly powerful.
Bundler scripts are ruby code veiled in a thin DSL which defines the external dependencies in one place (in addition it has a GemFile.lock which ensures other developers will use the same packages that you are based on all of your packages’ dependency versioning requirements). Again, we can look to the elegant simplicity of the Albacore Gemfile for an example.
The ruby community has fully embraced their language, package management system, and made them first class citizens. When you clone a repo, you execute ‘bundle install’ and all of your dependencies are pulled down. You do this once. From then on you can check for updates, verify that packages are up-to-date, and all other dependency lifecycle tasks. You can also manage your gem projects with the Jewler gem; it has some very enticing features (if you looked at the Albacore gemspec, you likely saw that it is generated by Jewler).
What about NuGet?
NuGet defines its specs with XML. And to be all great and powerful XML, it is schema validated. Ninety-three percent of the first three lines of a package are copy & paste noise. This is a waste of time and hides the intent of the spec.
NuGet defines its dependencies with XML and manages its local package configurations with a repositories.config file and many, many packages.config files. Each of these packages.config files are stored in each project folder. If you use NuGet, the way it is designed to work, you have no way of seeing what dependencies your application actually has without loading your solution into VS and making sure that all of these config files are checked in across your codebase.
Examples
Let’s start by taking a look at a simple spec definition.
123456789101112131415
<?xml version="1.0"?><packagexmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:xsd="http://www.w3.org/2001/XMLSchema"><metadataxmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd"><id>Ninject</id><version></version><authors>Ninject Project Contributors</authors><requireLicenseAcceptance>true</requireLicenseAcceptance><licenseUrl>https://github.com/ninject/ninject/raw/master/LICENSE.txt</licenseUrl><summary>IoC container for .NET</summary><language>en-US</language><tags>Ninject ioc di</tags><iconUrl>https://github.com/ninject/ninject/raw/master/logos/Ninject-Logo32.png</iconUrl><projectUrl>http://www.ninject.org</projectUrl></metadata></package>
Pulling directly from Giles rakefile which uses Albacore to generate the XML spec:
1234567891011121314151617181920212223
desc"Create the nuspec"nuspec:createSpec=>:prepPackagedo|nuspec|nuspec.id="Giles"nuspec.version=@GilesVersionnuspec.authors="Jeff Schumacher (@codereflection)"nuspec.owners="Jeff Schumacher (@codereflection)"nuspec.description="Giles - continuous test runner for .NET applications."nuspec.summary="Currently supports Machine.Specifications (mspec), NUnit, xUnit.net, and NSpec"nuspec.language="en-US"nuspec.projectUrl="http://testergiles.herokuapp.com/"nuspec.title="Giles, Rupert Giles, at your service!"nuspec.tags="testrunner test unittest giles"nuspec.output_file="Giles.nuspec"nuspec.working_directory="deploy/package"nuspec.licenseUrl="https://github.com/codereflection/Giles/blob/master/License.txt"enddesc"Create the nuspec package"nugetpack:createPackagedo|nugetpack|nugetpack.nuspec="deploy/package/Giles.nuspec"nugetpack.base_folder="deploy/package"nugetpack.output="deploy"end
We can replicate this with a simple PowerShell script where we give the user a simple object which properties are attached.
There are additional properties such as dependencies, frameworkAssemblies, and files. With a scripted definition, these nodes are very simple, and we can actually use file sets and collections to specify values instead of wildcards and long lists.
In the Beginning
Perhaps the craziest part is that NuGet started with Nubular (Nu), which was implemented via ruby gems. Let that sink in for a moment. The package management system for .NET was once ruby based. Here is an original package definition for AutoFac
12345678910111213
version=File.read(File.expand_path("../VERSION",__FILE__)).stripGem::Specification.newdo|spec|spec.platform=Gem::Platform::RUBYspec.name='autofac'spec.version=versionspec.files=Dir['lib/**/*']+Dir['docs/**/*']spec.summary='Autofac - An addictive .NET IoC container'spec.description='Autofac is an IoC container for Microsoft .NET. It manages the dependencies between classes so that applications stay easy to change as they grow in size and complexity. This is achieved by treating regular .NET classes as components.'spec.authors=['Nicholas Blumhardt','Rinat Abdulin']spec.email='emailme@bilsimser.com'spec.homepage='http://code.google.com/p/autofac/'spec.rubyforge_project='autofac'end
If you go to the Nu website, you’ll see this at the top:
February 2011 - The collaborative effort of the Nubular team and Microsoft has produced NuGet.
I wasn’t involved, but it seems to me that collaborative is a synonym for neutering. They took a thriving ecosystem with working solution and then stepped back years technologically. Microsoft couldn’t embrace Ruby; especially with the way it abandoned IronRuby. NuGet became the TFS of package management: highly integrated and doing nothing well.
Package Restore
I traveled to Portland and paired up with another developer to try to cut some code. We pulled down a repo, and then proceeded to trip all over ourselves…err, NuGet…for quite a while. The project we were dealing with, unsurprisingly, relied on NuGet package restore.
We were surprised at every step dealing with packages hooking into the csproj targets, build steps, and tooling incompatibilities. In the end, we changed frameworks and were finally able to rip out NuGet’s parasitic attachment to our project.
NuGet package restore is a feature in which NuGet embeds itself into your project files
1234567
<project><propertyGroup><RestorePackages>true</RestorePackages></propertyGroup><!-- your project contents--><ImportProject="$(SolutionDir)\.nuget\nuget.targets"/></project>
It also creates a .nuget folder at your solution root which contains NuGet.config, NuGet.exe, and NuGet.targets.
When you pull down a project/solution that uses package restore, and then try to build it, you get an error (well, many errors most likely, but they are the same). NuGet, through its targets hook, will call:
Where <PathTo> is changed for every packages.config littered in your codebase.
12345
C:\Dev\SomeProject\.nuget\NuGet.targets(80,9): error : Package restore is disabled by default.
To give consent, open the Visual Studio Options dialog, click on Package Manager node and
check 'Allow NuGet to download missing packages during build.' You can also give consent by
setting the environment variable 'EnableNuGetPackageRestore' to 'true'. [C:\Dev\SomeProject\src\SomeProject\SomeProject.csproj]
C:\Dev\SomeProject\.nuget\NuGet.targets(80,9): error : One or more errors occurred. [C:\Dev\SomeProject\src\SomeProject\SomeProject.csproj]
So, now I need to either open Visual Studio and find the setting they list, or I need to create an environment variable and set the value to true. Now, we have to configure package restore on each developer’s machine, plus the build server to deal with this requirement.
There is something more insidious hiding inside your build due to package restore. When you run your build, it is not a one-time install of your application’s dependencies. NuGet will run a package install for every single package in every project that has a packages.config file. Let’s look at the log output from building a solution with package restore:
123456
> msbuild SomeProject.sln
...
RestorePackages:
"C:\dev\SomeProject\.nuget\nuget.exe" install "C:\dev\SomeProject\src\SomeProject\packages.config
" -source "" -RequireConsent -solutionDir "C:\dev\SomeProject\ "
All packages listed in packages.config are already installed.
The build will always run the nuget.exe install call for every build. Every build you have is now slower, and will be slower still for each project you add that makes this redundant call (nuget will detect that the packge is already installed, but it is still slowing your build and filling your logs with garbage).
NuGet is also dealing with privacy issues related to package restore. Had the NuGet team stuck with Nu’s original implementation, there would have never been a need for package restore with everything handled with Bundler. Ruby’s gem system isn’t the greatest in the world, and there are growing numbers of people that are talking about trying something else, but they are still years ahead of the NuGet.
NuGet.exe
NuGet on the command line is a shadow of its Package Manager Console self. NuGet.exe:
Can’t update a package, let alone all, without being given a packages.config file. (I hear this is being fixed)
Can’t remove a package, at all.
Does not run init.ps1, install.ps1, or uninstall.ps1 leaving your packages broken when used outside of Visual Studio. You don’t have a DTE instance, so even if the scripts were executed, they wouldn’t work. Package installation has been designed to force a user into Visual Studio to install a dependency.
With the config parameter: gets or sets NuGet config values - except that you don’t know what keys exist so you can’t see the config values.
When using packages.config will get the exact version in the file no matter what.
Doesn’t get dependencies at all when using packages.config; they are expected to be in the file already.
You can’t specify a compatible set of versions in your packages.config files should one or more of your dependencies require a different, but still compatible version of a shared dependency. I can hear you objecting with “you can use allowedVersions”:
This however, doesn’t work; it is broken by design. Using allowedVersions means you’d have to track down every packages.config file and manually edit it to add this attribute. Even worse, NuGet looks at each packages.config individually so it can’t see version compatibility issues with allowedVersions.
NuGet appends the version of the library to the name when creating a folder in the Packages folder. This means that any updates require you to update every one of your project files with a new file path. This is a weak argument, but we should be given an easy way to override this without manually creating the calls to nuget.exe or install-package.
One item, that may be the coup de grâce of NuGet’s feature failings relates to how package sources are specified. How do you know where a particular dependency is sourced? We can see an example with xUnit. If we open the xunit NuGet.targets file:
When you look at a dependency, you have no idea where that dependency is coming from. NuGet will have to check each feed to find where a particular package resides. What happens if the package is in both feeds? What if you want the version from your own feed to be used? This is just another example of making the tool work like magic and finding yet another place to configure NuGet.
Now, to figure out what dependencies I have, and where they come from, I have to look through three different types of XML files. Even though once I have done that, I may not know where those dependencies even come from.
The End?
Will I stop using NuGet? No. Will I be happy using it? No. Will I stop complaining? Hell no. Pretending that everything is great will never push us to do better. I’ll do everything I can to remove NuGet’s way of doing things and put in my own.
Finishing Questions
Do we host a new gems website and write some importer form nuget to convert packages to gems?
Will we write something gemlike?
Can we analyze gems’ and NuGet’s failings to design a better system?
Can we create tooling around a cross platform DSL other than XML?
The use of PowerShell and reliance on Visual Studio really hurts mono development on Linux using nuget. What could we use instead? Can we push Microsoft to make PowerShell OSS?
Can Nemerle be leveraged to create a DSL that will work for mono as well?
Do we rewrite nuget the correct way? Correct being first class, OS independent CLI and no XML. The CLI is the most important thing in most camps. It should be the case, but it obviously isn’t since MS took over NuGet. There is a whole camp that thinks the GUI is the most important thing; then there is MS that tries to make all free things tie into paid products somehow. They would be wrong. I understand their perspective, but it is the wrong choice. When developing free software, choose to do it right. By creating the deep integration into Visual Studio and abandoning the command line, we are forced to use Visual Studio in order to leverage NuGet, thus destroying any competition.
In .NET 4.0, we have access to the Dynamic Language Runtime (DLR) giving us dynamic dispatch via the IDynamicMetaObjectProvider interface coupled with the dynamic keyword. When a variable is declared as dynamic and it implements the IDynamicMetaObjectProvider interface, we are given the opportunity to control the delegation of calls on that object by returning a DynamicMetaObject containing an expression which will be evaluated by the runtime. We only get this opportunity if the direct target was unable to directly handle the expression.
The DynamicObject and ExpandoObject classes both implement IDynamicMetaObjectProvider, but their implementations are explicitly implemented and the nested classes used to return the DynamicMetaObject are private and sealed. I understand that the classes may not have been tested enough to make them inheritable, but not having access to these classes really hurts our ability to easily modify the behavior of the underlying DynamicMetaObject. The key word here is easily; implementing the needed expression building is a great deal of work and the internal workings of the Microsoft implementations leverage many internal framework calls.
A key thing to consider is that we don’t want to replicate classical inheritance; instead, we are going to focus on prototypal inheritance that mostly replicates JavaScript’s prototypal inheritance. Rather than trying to replicate all of the hard work that the DRL team put into writing their implementation, we can add our own implementation on top of theirs. It is simple to hook in, but we need to save off a method to access the base DynamicMetaObject implementation. This will allow us to attempt to interpret the expression on the object itself or pass it along.
This small amount of code just sets the hook. Now we need set up the delegation expression.
To set up the prototypal hierarchy, we are going to need to do a lot of recursion. Unfortunately, it is well hidden (I’ll explain shortly). When a call is made on the root object, we are given the expression being interpreted. Using the IDynamicMetaObjectProvider overload, we will hand off the expression to the PrototypalMetaObject to construct delegation expression (or the DynamicObject implementation if our prototype is null thus trying to interpret the expression on the current object). We want to make a preorder traversal of the prototype hierarchy; at each step, the current object’s evaluation will take precedence over its prototype tree. Consider the following prototypal class hierarchy:
Since we never know which level of the hierarchy will be handling the expression, we need to build an expression for the entire tree every time. We want to get the DynamicMetaObject representing the current object’s tree first. Once done, we get the DynamicMetaObject for evaluating the expression on the current instance. With these two, we can create a new DynamicMetaObject which try to bind the expression to the current instance first, and then fallback to the prototype. At the root level, the prototype DynamicMetaObject contains the same fallback for the next two layers.
There is another caveat that we need to address. When we try to invoke and expression on an object, the expression is bound to that type. When accessing the prototype, if we don’t do anything, the system will throw a binding exception because the matching object won’t match the DynamicMetaObject’s type restrictions. To fix this, we need to relax the type restrictions for each prototype.
To iterate is human, to recurse is divine, to inception recurse is demented
Remember the recursion I mentions earlier? In the code sample below, I have pulled out all binding code except for the BindInvokeMember method. The _metaObject.Bind[...] will actually call into DelegatingPrototype::GetMetaObject which will try to call back into _metaObject.Bind[...], which will…well you get the idea. At each call, the prototype becomes the target and we get a new prototype.
You may be thinking, ok, this is cool, but what use it is it? What is the use case? First, it’s cool. Second, it sets the foundation for .NET mixins. Third, it gives us a second form of inheritance (after parasitic) for PowerShell.
What if we take the prototype and make it a collection of prototypes? What if instead of inheriting from DelegatingPrototype we reuse the internal prototypal skeleton? If this sounds familiar, it should. I am describing ruby classes with modules and a base class, but with C#…
If you want to see more or play around with the code, you can find full implementations in the Archetype project.
The sum of the primes below 10 is 2 + 3 + 5 + 7 = 17.
Find the sum of all the primes below two million.
This problem is very simple as I can reuse the parasitic prime generation from my solution to Problem 7 which also requires Prototype.ps.
123456789101112131415161718192021222324
functionNew-PrimeFinder{$prototype=New-PrimeGenerator$prototype|Add-FunctionFindPrimesLessThan{param($value)if($this.Bound-lt$value){$finder.BoundIncrement=$value-$this.Bound$this.Expand()}return$this.Primes|?{$_-lt$value}}$prototype}functionSolve-Problem10{param($value=2000000)$finder=New-PrimeFinder$finder.FindPrimesLessThan($value)|%{[long]$sum=0}{$sum+=$_}{$sum}}Write-Host"Elapsed Time (s): "(Measure-Command{Solve-Problem10}).TotalSecondsWrite-Host"Solution: "(Solve-Problem10)ElapsedTime(s):1999.6739304Solution:142913828922
A Pythagorean triplet is a set of three natural numbers, a < b < c, for which, a^2 + b^2 = c^2 For example, 32 + 42 = 9 + 16 = 25 = 52.
There exists exactly one Pythagorean triplet for which a + b + c = 1000. Find the product abc.
123456789101112131415161718192021222324
functionSolve-Problem9{$sum=1000$found=$falsefor($a=1;$a-lt$sum/3;$a++){for($b=$a;$b-lt$sum/2;$b++){$c=$sum-$a-$bif($a*$a+$b*$b-eq$c*$c){$found=$truebreak}}if($found){break}}Write-Host"The Pythagorean triplet is a = $a, b = $b, c = $c"Write-Host"The product is $($a*$b*$c)"}Write-Host"Elapsed Time (s): "(Measure-Command{Solve-Problem9}).TotalSecondsThePythagoreantripletisa=200,b=375,c=425Theproductis31875000ElapsedTime(s):0.2247551
functionSplit-Number{param([string]$value)$index=0while($index-lt$value.Length-4){$value.Substring($index++,5)}}filterEvaluate-String{$_.ToCharArray()|%{[int]::Parse($_)}|%{$total=1}{$total*=$_}{$total}}functionSolve-Problem8{$text="7316717653133062491922511967442657474235534919493496983520312774506326239578318016984801869478851843858615607891129494954595017379583319528532088055111254069874715852386305071569329096329522744304355766896648950445244523161731856403098711121722383113622298934233803081353362766142828064444866452387493035890729629049156044077239071381051585930796086670172427121883998797908792274921901699720888093776657273330010533678812202354218097512545405947522435258490771167055601360483958644670632441572215539753697817977846174064955149290862569321978468622482839722413756570560574902614079729686524145351004748216637048440319989000889524345065854122758866688116427171479924442928230863465674813919123162824586178664583591245665294765456828489128831426076900422421902267105562632111110937054421750694165896040807198403850962455444362981230987879927244284909188845801561660979191338754992005240636899125607176060588611646710940507754100225698315520005593572972571636269561882670428252483600823257530420752963450"(Split-Number$text|Evaluate-String|Measure-Object-Maximum).Maximum}Write-Host"Elapsed Time (s): "(Measure-Command{Solve-Problem8}).TotalSecondsWrite-Host"Solution: "(Solve-Problem8)ElapsedTime(s):0.5708985Solution:40824
This post leverages my OSS project Prototype.ps to support parasitic object creation. If you haven’t read the introduction posts Part 1 and Part 2, I would recommend reading them as I build off of their functionality and theory. If you don’t care how it works, read on my friend.
By listing the first six prime numbers: 2, 3, 5, 7, 11, and 13, we can see that the 6th prime is 13.
functionNew-PrimeGenerator{$prototype=New-Prototype$prototype|Update-TypeName$prototype|Add-PropertyPrimes@(2,3,5)$prototype|Add-PropertyCache@{2=$true;3=$true;4=$false;5=$true}$prototype|Add-PropertyBound5$prototype|Add-PropertyBoundIncrement1000$prototype|Add-PropertyLastExpansionPrimeCount3$prototype|Add-ScriptPropertyMaxPrime{$this.Primes|select-last1}$prototype|Add-FunctionIsPrime{param($value)while($this.MaxPrime-lt$value){$this.Expand()}return$this.Cache[$value]-ne$null}$prototype|Add-FunctionFindNthPrime{param($value)while($this.Primes.Length-lt$value){$this.Expand()}return$this.Primes[$value-1]}$prototype|Add-FunctionRoundToNextMultiple{param($base,$multiple)$remainder=$base%$multiple;if($remainder-eq0){$base}else{$base+$multiple-$remainder}}$prototype|Add-FunctionExpand{$oldBound=$this.Boundif($this.LastExpansionPrimeCount-le$this.Primes.Length){$this.Bound+=$this.BoundIncrement}$limit=$this.Bound$cache=$this.Cache$this.Primes|%{for($i=$this.RoundToNextMultiple($oldBound,$_);$i-le$limit;$i+=$_){if(!$cache.ContainsKey($i)){$cache[$i]=$false}}}($oldBound+1)..$limit|?{$cache[$_]-eq$null}|%{$cache[$_]=$true$this.Primes+=@($_)for($i=$this.RoundToNextMultiple($oldBound,$_);$i-le$limit;$i+=$_){if(!$cache.ContainsKey($i)){$cache[$i]=$false}}}$this.LastExpansionPrimeCount=$this.Primes.Length}$prototype}functionSolve-Problem7{$generator=New-PrimeGeneratorWrite-Host"Elapsed Time (s): "(Measure-Command{$generator.FindNthPrime(10001)}).TotalSecondsWrite-Host"Elapsed Time (s): "(Measure-Command{$generator.FindNthPrime(10001)}).TotalSecondsWrite-Host"Solution: "($generator.FindNthPrime(10001))}Solve-Problem7ElapsedTime(s):33.1381042ElapsedTime(s):0.0003987Solution:104743
The sum of the squares of the first ten natural numbers is,
1^2 + 2^2 + … + 10^2 = 385 The square of the sum of the first ten natural numbers is,
(1 + 2 + … + 10)^2 = 55^2 = 3025 Hence the difference between the sum of the squares of the first ten natural numbers and the square of the sum is 3025-385 = 2640.
Find the difference between the sum of the squares of the first one hundred natural numbers and the square of the sum.
1234567891011
functionSolve-Problem6{$sum=(1..100|Measure-Object-Sum).Sum$sumOfSquares=(1..100|%{$_*$_}|Measure-Object-Sum).Sum$sum*$sum-$sumOfSquares}Write-Host"Elapsed Time (s): "(Measure-Command{Solve-Problem6}).TotalSecondsWrite-Host"Solution: "(Solve-Problem6)ElapsedTime(s):0.0115265Solution:25164150
2520 is the smallest number that can be divided by each of the numbers from 1 to 10 without any remainder.
What is the smallest positive number that is evenly divisible by all of the numbers from 1 to 20?
The next problem is just folding two values from an array and replacing them with their LCM, then run again and again until only one item is left in the collection (and you now have the LCM of all entries).
functionGet-Gcd{param($lhs,$rhs)if($lhs-eq$rhs){return$rhs}if($lhs-gt$rhs){$a,$b=$lhs,$rhs}else{$a,$b=$rhs,$lhs}while($a%$b-ne0){$tmp=$a%$b$a,$b=$b,$tmp}return$b}functionGet-Lcm{param($lhs,$rhs)[long][Math]::Abs($lhs*$rhs)/(Get-Gcd$lhs$rhs)}functionGet-LcmOfGroup{param([int[]]$values)$lhs=$values[0]$rhs=$values[1]$lcm=Get-Lcm$lhs$rhs$values=@($lcm)+$values[2..$values.Length]if($values.Length-eq1){return$lcm}else{Get-LcmOfGroup$values}}functionSolve-Problem5{Get-LcmOfGroup@(1..20)}Write-Host"Elapsed Time (s): "(Measure-Command{Solve-Problem5}).TotalSecondsWrite-Host"Solution: "(Solve-Problem5)ElapsedTime(s):0.0407472Solution:232792560