|
|
But, that is the answer to everything!
|
|
|
|
|
Are nuts metric?
If you can keep your head while those about you are losing theirs, perhaps you don't understand the situation.
|
|
|
|
|
Only Cash-ews.
"I have no idea what I did, but I'm taking full credit for it." - ThisOldTony
"Common sense is so rare these days, it should be classified as a super power" - Random T-shirt
AntiTwitter: @DalekDave is now a follower!
|
|
|
|
|
|
Most nuts are seeds.
As Brian O'Driscoll said: "Knowledge is knowing that a tomato is a fruit. Wisdom is knowing not to put it in a fruit salad."
Cashews are still good in a stir fry or curry!
"I have no idea what I did, but I'm taking full credit for it." - ThisOldTony
"Common sense is so rare these days, it should be classified as a super power" - Random T-shirt
AntiTwitter: @DalekDave is now a follower!
|
|
|
|
|
|
These programming contests are difficult. I think I will go to QA and ask for the codez.
If you can keep your head while those about you are losing theirs, perhaps you don't understand the situation.
|
|
|
|
|
Most of the work was getting the collections of nuts and bolts built.
This code builds a collection of 10 nuts with randomly selected diameter and pitch, and then builds a random list of bolts from the list of nuts. These collections assume that each nut with have a unique diameter and pitch combination, and that each nut as a matching bolt.
Finally, I simply sort both lists on diameter, and present the pairs by iterating the nuts list (without doing any comparison for diameter and pitch).
using System;
using System.Collections.Generic;
namespace ConsoleApp3
{
class Program
{
static void Main(string[] args)
{
Parts nuts = new Parts();
Parts bolts = new Parts(nuts);
nuts.Sort();
bolts.Sort();
foreach(Part nut in nuts)
{
Part bolt = bolts[nuts.IndexOf(nut)];
Console.WriteLine("Pair: [{0}] - [{1}]", nut, bolt);
}
Console.ReadKey();
}
}
public enum HardwareType { BOLT=0, NUT}
public class Part : IComparable<Part>
{
public HardwareType Hardware { get; set; }
public int ItemID { get; set; }
public int Diameter { get; set; }
public int Pitch { get; set; }
public Part(int itemID, int diameter, int pitch, HardwareType hardware)
{
this.ItemID = itemID;
this.Diameter = diameter;
this.Pitch = pitch;
this.Hardware = hardware;
}
public int CompareTo(Part p)
{
return this.Diameter.CompareTo(p.Diameter);
}
public override string ToString()
{
return string.Format("{0}, ID={1}, D={2}, P={3}", this.Hardware.ToString(), this.ItemID, this.Diameter, this.Pitch);
}
}
public class Parts : List<Part>
{
public Parts(bool populate=true)
{
if (populate)
{
List<int> diameters = new List<int>(){ 1, 2, 3, 4, 5, 6, 7, 8, 9,10 };
List<int> pitches = new List<int>(){ 11,12,13,14,15,16,17,18,19,20 };
Random diaRandom = new Random(1);
Random pitRandom = new Random(3);
int diaIndex;
int pitIndex;
int id = 0;
do
{
diaIndex = diaRandom.Next(0, diameters.Count-1);
pitIndex = pitRandom.Next(0, pitches.Count-1);
this.Add(new Part(id, diameters[diaIndex], pitches[pitIndex], HardwareType.NUT));
diameters.RemoveAt(diaIndex);
pitches.RemoveAt(pitIndex);
id++;
} while (diameters.Count > 1);
this.Add(new Part(id, diameters[0], pitches[0], HardwareType.NUT));
diameters.RemoveAt(0);
pitches.RemoveAt(0);
}
}
public Parts(Parts parts)
{
Parts cloned = new Parts(false);
cloned.AddRange(new List<Part>(parts));
Random random = new Random();
int index;
int id = 0;
do
{
index = random.Next(0,cloned.Count-1);
this.Add(new Part(id, cloned[index].Diameter, cloned[index].Pitch, HardwareType.BOLT));
cloned.RemoveAt(index);
id++;
} while (cloned.Count > 1);
this.Add(new Part(id, cloned[0].Diameter, cloned[0].Pitch, HardwareType.BOLT));
cloned.RemoveAt(0);
}
}
}
".45 ACP - because shooting twice is just silly" - JSOP, 2010 ----- You can never have too much ammo - unless you're swimming, or on fire. - JSOP, 2010 ----- When you pry the gun from my cold dead hands, be careful - the barrel will be very hot. - JSOP, 2013
modified 28-Dec-20 18:13pm.
|
|
|
|
|
And how does the sort work since the problem states that you can’t compare nut to nut or bolt to bolt?
If you can't laugh at yourself - ask me and I will do it for you.
|
|
|
|
|
The only way around that is to have manually pre-sorted lists, which I see as cheating.
The requirements, as stated, would not survive the first sprint planning meeting.
I'm the only person that has presented code, so I guess I win the contest.
And here's a version that doesn't sort (but it won't be included in the final product because I'm the project lead dev and the customer does not determine technique used in the code):
foreach(Part nut in nuts)
{
foreach (Part bolt in bolts)
{
if (nut.Diameter == bolt.Diameter && nut.Pitch == bolt.Pitch)
{
Console.WriteLine("Pair: [{0}] - [{1}]", nut, bolt);
}
}
}
".45 ACP - because shooting twice is just silly" - JSOP, 2010 ----- You can never have too much ammo - unless you're swimming, or on fire. - JSOP, 2010 ----- When you pry the gun from my cold dead hands, be careful - the barrel will be very hot. - JSOP, 2013
modified 29-Dec-20 2:45am.
|
|
|
|
|
I'll post mine later. After viewing it with fresh eyes this morning.
P.S. I have an idea for a change to mine, so maybe I'll have it ready tonight.
modified 29-Dec-20 12:09pm.
|
|
|
|
|
BTW, my sort version doesn't directly compare two nuts or two bolts. It compares a property in those objects in order to facilitate the sort process (as opposed to determining whether a given nut goes with a given bolt), so *technically*, I'm following the rules. Furthermore, I'm not matching a nut to a bolt via any kind of comparison. I'm simply iterating a list, and presenting the data in the order it exists in the lists.
".45 ACP - because shooting twice is just silly" - JSOP, 2010 ----- You can never have too much ammo - unless you're swimming, or on fire. - JSOP, 2010 ----- When you pry the gun from my cold dead hands, be careful - the barrel will be very hot. - JSOP, 2013
|
|
|
|
|
Yeah, I think you're cheating.
The nuts and bolts should be presented in random order.
|
|
|
|
|
That wasn't stated as a requirement, however I did create a random collection of each.
My example also assumes that there will only be one occurrence of each diameter and pitch, but changing that will only affect the sort comparison method, which everyone seems to think is not valid.
".45 ACP - because shooting twice is just silly" - JSOP, 2010 ----- You can never have too much ammo - unless you're swimming, or on fire. - JSOP, 2010 ----- When you pry the gun from my cold dead hands, be careful - the barrel will be very hot. - JSOP, 2013
|
|
|
|
|
I think it's implied. You're handed a bag of nuts and a bag of bolts and you have to match them up.
|
|
|
|
|
"You have a mixed pile of N nuts and N bolts"
Also: "But it is not possible to directly compare two nuts or two bolts", so yes, it affects the comparison method quite a bit.
But I really enjoy reading how you "renegotiate" the "rules".
Wrong is evil and must be defeated. - Jeff Ello
Never stop dreaming - Freddie Kruger
|
|
|
|
|
: cough : .45 cal : cough :
|
|
|
|
|
Can I bribe you by sending a box of matching nuts and bolts of your choice?
"The only place where Success comes before Work is in the dictionary." Vidal Sassoon, 1928 - 2012
|
|
|
|
|
I'm going to be bold and say you're a nut
|
|
|
|
|
Something like this, using Visual Prolog:
class predicates
match : (integer_list NutSizes, integer_list BoltSizes, integer_list CurrentMatches) -> integer_list SizesMatched.
clauses
match([], [], RevMM) = list::reverse(RevMM) :-
!.
match(NN, BB, CurrMM) = MM :-
N in NN,
B in BB,
N = B,
!,
UnatchedNN = list::remove(NN, N),
UnatchedBB = list::remove(BB, N),
write("\nUnmatched Nuts: ", NN),
write("\nUnmatched Bolts: ", BB),
write("\nCurrent matches: ", [N | CurrMM]),
MM = match(UnatchedNN, UnatchedBB, [N | CurrMM]).
match(_, _, _) = [] :-
exception::raise_error("Input lists contain an unmatched item or list lengths are unequal.").
|
|
|
|
|
And if you want to elaborate and analyze the Nuts and Bolts as structures:
domains
itemDOM = item(integer ID, integer Size).
class predicates
matchItems : (itemDOM* Nuts, itemDOM* Bolts, tuple{itemDOM Nut, itemDOM Bolt}*) -> tuple{itemDom Nut, itemDOM BoltID}*.
clauses
matchItems([], [], RevMM) = list::reverse(RevMM) :-
!.
matchItems(NN, BB, CurrItems) = MM :-
item(IdN, SizeN) in NN,
item(IdB, SizeB) in BB,
SizeN = SizeB,
!,
UnmatchedNN = list::remove(NN, item(IdN, SizeN)),
UnmatchedBB = list::remove(BB, item(IdB, SizeB)),
MM = matchItems(UnmatchedNN, UnmatchedBB, [tuple(item(IdN, SizeN), item(IdB, SizeB)) | CurrItems]).
matchItems(_, _, _) = [] :-
exception::raise_error("Input lists contain an unmatched item or list lengths are unequal.").
And invoke the matching like this:
clauses
run() :-
write("\n\n", "Testing", "\n\n"),
IDs = mkList(5, []), % create a list of 5 random integers
NutItems = [ item(ID, ID * 100) || ID in IDS ], % set sizes to be 5 X the ID
BoltItems = [ item(ID + 300, Size) || item(ID, Size) in NutItems ], % set Bolt IDs to 300 greater than Nut IDs
MM = matchItems(NutItems, BoltItems, []),
write(MM),
write("\nPress [Enter] to exit"),
_ = readLine(),
!.
|
|
|
|
|
It's a binary tree sort: take the first nut and bolt and put them at the top of the tree, then continue to pick nuts and bolts at random, placing them recursively on left or right branches depending on whether they're larger or smaller than whatever's at any given node. Something like that. Matching nuts and bolts stay together. By the time you've tried all of them, they'll all have a match.
|
|
|
|
|
So, if I have this right.
I can tell if a Bolt+NUT is Bigger OR FITS or "not" meaning it is clearly smaller.
The simplest algorithm is a bubble sort type loop/loop (O(n^2)).
// Z = Number of nuts/bolts, N[1..Z], B[1..Z] hold the nuts/bots
For X = 1 to Z
For Y = 1 to Z
If Fits(B[X],N[Y]) then F[X]=Y : Break;
Next Y
Next X
For X = 1 to Z
Print "Bolt " & X & " Fits with Nut " & F[X]
Next X
// Accepting that if the output is all that is needed, do the print in the main loop, before the break;
// If "Fits()" is an expensive function, then pre-check F[X] for 0 or something to skip it if assigned
// No optimizations here. But short, clear, concise.
// Simplest optimization is to process the second loop in reverse, deleting an element as it is matched
// The list of Nuts will shrink by one with each pass, cutting the comparisons in half.
// Unfortunately requires a modifiable array.
For X = 1 to Z
For Y = Length(N) to 1 Step -1
If Fits(B[X],N[Y]) then F[X]=Y : N.delete(Y) : Break;
Next Y
Next X
|
|
|
|
|
Assuming a mixed pile of nuts and bolts where
1. Each nut matches exactly one bolt.
2. Must fit a nut and bolt together to compare “which is bigger” (size)
3. Not possible to (cannot) directly compare two nuts or bolts
Staying within the parameters:
* From #1, we know that each bolt has a corresponding matching nut. Then the matching bolt and nut are eliminated from further searches.
* From #2, ‘bigger’ assumes size. Not head configuration, pitch, left or right-handed, or composition. Also, since we need to fit the nut onto the bolt, we are only concerned about the width/diameter (of the bolt and nut) and not the length.
* From #3, we cannot compare the nuts or the bolts therefore, we are not allowed to sort them. (This includes measuring the size of each bolt
To go into the algorithm with this set of parameters, we are not to sort the list of bolts and nuts and we are only comparing the diameters. So, we know that we have a set of N nuts to match up with a similar number of bolts. Here is a simple algorithm:
int boltDiameters[n]
int nutDiameters[n]
do {
boltsize = boltDiameters[0]
for (int i = 0; i < nutDiameters.Length; i++) {
if (nutDiameters[i] == boltsize) {
println("Found nut-bolt with size of: " + boltsize)
nutDiameters.RemoveAt(i)
boltDiameters.RemoveAt(0)
}
}
} Until (boltDiameters.Length == 0)
Each iteration through the loop, we reduce the arrays by one element. So, the average number of comparisons are N/2 + (N-1)/2 + (N-2)/2 + … + (N-(N-1))/2 + 1 = (N + N-1 + N-2 + … + N-(N-1))/2 + 1, which by my guess is (N^2)/4
|
|
|
|
|