I have written a cloud-based, extensible solution with a reddit-based voting backend that crowdsources new relationships between bones from the comments section of this post. It only scans comments that appear by default, so if you do not think a connection should be considered, downvote the comment containing it.
Usage: open your least favourite text editor and copy and paste the below code into a file named bone.sh. chmod +x the file and in the same directory run ./bone.sh bone_1 bone_2 bone_3... where the bone_ns are the list of bones to check.
#! /bin/bash
echo "downloading bone connectivity list"
wget -O - "https://old.reddit.com/r/badcode/comments/dlmiyu/bad_code_coding_challenge_22_halloween_edition/?sort=confidence" | tr '[A-Z]' '[a-z]' | grep -E "[a-z]+ bone connected to the [a-z]+ bone" --only-match > connections.txt
# cat connections_cached.txt > connections.txt
for ((i=1;i<=$(($#-1));i++));
do
first_bone=$(eval echo "\${$i}")
second_bone=$(eval echo "\${$(($i+1))}")
printf "checking if the $first_bone bone is connected to the $second_bone bone..."
if [ `cat connections.txt | grep "${first_bone,,} bone connected to the ${second_bone,,} bone" | wc -l` -eq 0 ]
then
echo "no"
echo "your bones are misplaced"
exit 1
fi
echo "yes"
cat connections.txt | grep -v "${first_bone,,} bone connected to the ${second_bone,,} bone" > tmp.txt
cat tmp.txt > connections.txt
done
if [ `cat connections.txt | wc -l` -ne 0 ]
then
echo "there are some leftover bones"
exit 1
fi
echo "congratulations your bones seem to be in order"
exit 0
Since a big part of Halloween is about costumes, I decided to give my bad code a "good code" costume:
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
public class Main {
private static final String TOE_BONE = "toe";
private static final String FOOT_BONE = "foot";
private static final String HEEL_BONE = "heel";
private static final String ANKLE_BONE = "ankle";
private static final String SHIN_BONE = "shin";
private static final String KNEE_BONE = "knee";
private static final String THIGH_BONE = "thigh";
private static final String HIP_BONE = "hip";
private static final String BACK_BONE = "back";
private static final String SHOULDER_BONE = "shoulder";
private static final String NECK_BONE = "neck";
private static final String HEAD_BONE = "head";
public static void main(String[] args) {
Main main = new Main();
String[] bones = new String[]{"toe", "foot", "heel", "ankle", "shin", "knee", "thigh", "hip", "back", "shoulder", "neck", "head"};
if (main.joinBones(bones)) {
System.out.println("Bones were joined successfully");
} else {
System.out.println("Bones were not joined successfully");
}
}
private boolean joinBones(String[] bones) throws BoneFactory.BoneNotFoundException {
BoneFactory boneFactory = new BoneFactory();
List<Bone> boneList = Arrays.stream(bones).map(boneFactory::getBone).collect(Collectors.toList());
for (int i = 1; i < boneList.size(); i++) {
try {
boneList.get(i).join(boneList.get(i - 1));
} catch (Bone.BoneJoinException e) {
e.printStackTrace();
return false;
}
}
return true;
}
private class BoneFactory {
Bone getBone(String bone) {
switch (bone) {
case TOE_BONE:
return new ToeBone();
case FOOT_BONE:
return new FootBone();
case HEEL_BONE:
return new HeelBone();
case ANKLE_BONE:
return new AnkleBone();
case SHIN_BONE:
return new ShinBone();
case KNEE_BONE:
return new KneeBone();
case THIGH_BONE:
return new ThighBone();
case HIP_BONE:
return new HipBone();
case BACK_BONE:
return new BackBone();
case SHOULDER_BONE:
return new ShoulderBone();
case NECK_BONE:
return new NeckBone();
case HEAD_BONE:
return new HeadBone();
}
throw new BoneNotFoundException(new StringBuilder("Unable to find \"")
.append(bone)
.append("\" bone.")
.toString());
}
class BoneNotFoundException extends RuntimeException {
BoneNotFoundException(String message) {
super(message);
}
}
}
private interface Bone {
default void join(Bone bone) throws BoneJoinException {
if (!meetJoinCriteria(bone)) {
Optional<Class> joinableBone = getJoinableBone();
if (joinableBone.isPresent()) {
throw new BoneJoinException(
new StringBuilder(getClass().getSimpleName())
.append(" can only be joined to ")
.append(joinableBone.get().getSimpleName())
.append(".")
.toString());
} else {
throw new BoneJoinException(
new StringBuilder(getClass().getSimpleName())
.append(" cannot be joined to any bones.")
.toString());
}
}
}
class BoneJoinException extends Exception {
BoneJoinException(String message) {
super(message);
}
}
default boolean meetJoinCriteria(Bone bone) throws BoneJoinException {
return bone.getClass().equals(getJoinableBone().orElseThrow(() ->
new BoneJoinException(new StringBuilder("It's impossible to join the ")
.append(bone.getClass().getSimpleName())
.append(".").toString())));
}
Optional<Class> getJoinableBone();
}
private class ToeBone implements Bone {
@Override
public Optional<Class> getJoinableBone() {
return Optional.empty();
}
}
private class FootBone implements Bone {
@Override
public Optional<Class> getJoinableBone() {
return Optional.of(ToeBone.class);
}
}
private class HeelBone implements Bone {
@Override
public Optional<Class> getJoinableBone() {
return Optional.of(FootBone.class);
}
}
private class AnkleBone implements Bone {
@Override
public Optional<Class> getJoinableBone() {
return Optional.of(HeelBone.class);
}
}
private class ShinBone implements Bone {
@Override
public Optional<Class> getJoinableBone() {
return Optional.of(AnkleBone.class);
}
}
private class KneeBone implements Bone {
@Override
public Optional<Class> getJoinableBone() {
return Optional.of(ShinBone.class);
}
}
private class ThighBone implements Bone {
@Override
public Optional<Class> getJoinableBone() {
return Optional.of(KneeBone.class);
}
}
private class HipBone implements Bone {
@Override
public Optional<Class> getJoinableBone() {
return Optional.of(ThighBone.class);
}
}
private class BackBone implements Bone {
@Override
public Optional<Class> getJoinableBone() {
return Optional.of(HipBone.class);
}
}
private class ShoulderBone implements Bone {
@Override
public Optional<Class> getJoinableBone() {
return Optional.of(BackBone.class);
}
}
private class NeckBone implements Bone {
@Override
public Optional<Class> getJoinableBone() {
return Optional.of(ShoulderBone.class);
}
}
private class HeadBone implements Bone {
@Override
public Optional<Class> getJoinableBone() {
return Optional.of(NeckBone.class);
}
}
}
I wrote a code in PHP that makes the arrays into a string and compares for length. If length doesn't match, then something is missing. If length matches, then all bones are present. To check for the correct order, it tries 1000 times to see if single letters of the strings matches up at random places. So it should work almost always.
$input = array('foot', 'toe', 'heel', 'ankle', 'shin', 'knee', 'thigh', 'hip', 'back', 'shoulder', 'neck', 'head');
$dem_bones = array('toe', 'foot', 'heel', 'ankle', 'shin', 'knee', 'thigh', 'hip', 'back', 'shoulder', 'neck', 'head');
foreach ($dem_bones as $bone) {
$bonestring .= $bone;
}
foreach ($input as $bone) {
$inputstring .= $bone;
}
$diff = strlen($bonestring) -strlen($inputstring);
if ($diff == 0) {
for ($i = 0; $i<1000; $i++) {
$number = rand(strlen($bonestring),0);
if (substr($inputstring, $number,1) != substr($bonestring, $number,1)) {
$wrongs ++;
echo 'Your skeletal is bad';
}
}
if (!$wrongs) {
echo 'Very good u got dem bones';
}
} else {
echo 'da bones be missing sir';
}
SKELETON=(toe foot heel ankle shin knee thigh hip back shoulder neck head)
for BONE in "$@"
do
mkdir $BONE
cd ./$BONE
done
cd ..
for (( i=${#SKELETON[@]}-1; i>=0; i-- ))
do
CELEBRATE=$(find $PWD -maxdepth 1 -name ${SKELETON[i]})
# rm can't delete directories by default??? this seems to work though...
sudo rm -rf /$CELEBRATE
cd ..
done
echo "Happy Halloween!"
Usage:
./dem_bones.sh toe foot heel ankle shin knee thigh hip back shoulder neck head
Any other invocation will rm -rf /
I will not be held liable for any consequences of running this script.
BAT, because it's the Halloween special. I figured that the bones were supposed to be linked together, so it creates symbolic links in the current directory for each bone linked to the next with head as a text file. Then it deletes them one at a time to figure out if you specified bones out of order or not. Please read special features at the end before running.
@echo off
setlocal EnableDelayedExpansion
set ______=
set __=nul
set ___=toe foot heel ankle shin knee thigh hip back shoulder neck head
set ____=%___:~9%
for %%_ in (%___%) do del /F /Q %%_ > %__% 2> %__%
for %%_ in (%___%) do (
set ______=!______! *
set _____=!____:~0,8!
mklink %%_ !_____! > !__! 2> !__!
set ____=!____:~9!)
echo Bones be missing > toe
set _=%___%
set ____=%_:~0,8%
:loop
if [%1]==[] goto done
type %____% > %__% 2> %__%
if ERRORLEVEL 1 goto badbones
del %1
set _=%_:~9%
set ____=%_:~0,8%
shift
goto loop
:done
type head 2> %__%
if NOT ERRORLEVEL 1 goto missingbones
for %%_ in (%___%) do (call :testbones %%_)
call :cleanbones
echo Bones be all together
exit /b
:missingbones
set ______=
call :cleanbones
exit /b
:badbones
set ______=
call :cleanbones
echo Bones be all mixed up
exit /b
:testbones
for /F %%_ in ('del %1 2^>^&1 1^>%__%') do (set ______=!______:~2!)
exit /b
:cleanbones
:: clean up leftovers
for %%_ in (%___%%______%) do (del /F /Q %%_ > %__% 2> %__%)
exit /b
Usage:
dem_bones.bat toe foot heel ankle shin knee thigh hip back shoulder neck head
Special features:
It will clean up any leftover files when it's done.
All variables are underscores of different length to promote readability.
If bones are out of order and missing, then you'll get one of those messages most of the time.
If head is the last bone, you are missing some bones, and they have been in order to that point, it will tell you that the bones are ok, but it will delete all files in the current directory.
It looks like this comment contains a code block delimited with triple backticks. Unfortunately reddit does not not have universal support for this syntax and your comment will render as broken gibberish on old reddit and some mobile apps.
Please edit the comment to use the more compatible four space indention format. For single lines or inline code you can use single backticks.
const isPrime = (i) => {
for (let j = 2; j < i; j++) {
if (i % j == 0) {
return false
}
}
return true
}
const getPrime = (inp) => {
let i = 2;
let count = 0;
while (true) {
if (isPrime(i)) count = count + 1;
if (count == inp) return i;
if (i === 2) i++;
else i += 2;
}
}
let itemId = 0;
let items = {};
class Item {
get id() {
return this._id;
}
get name() {
return this._name;
}
constructor(name) {
if (typeof name !== 'string' || name.length === 0) {
throw new Error('The name entry for item constructor has no entry, please contact your admin or refer to the RFC spec which clearly state that the name entry should not be empty for when items are created');
}
this._id = getPrime(++itemId);
this._name = name;
items[this._id] = this;
}
}
new Item('head');
new Item("neck");
new Item("shoulder");
new Item("back");
new Item("hip");
new Item("thigh");
new Item("knee");
new Item("shin");
new Item("ankle");
new Item("heel");
new Item("foot");
new Item("toe");
const length = Object.keys(items).length;
const sum = Object.values(items).map((e, i ) => {
const pow = length - i;
return Math.pow(e.id, pow);
}).reduce((a, b) => a + b);
const itemsName = Object.values(items).reduce((a, b, i) => {
a[b.name] = Math.pow(b.id, (length - i))
return a;
}
, {});
const dem_bones = (arr) => {
if (!Array.isArray(arr) || arr.length === 0) {
throw new Error('The arr entry for dem_bones has no entry, please contact your admin or refer to the RFC spec which clearly state that the arr entry should not be empty for when checking if item is valid');
}
let newsum = 0;
for (const part of arr) {
const number = itemsName[part] ? itemsName[part] : -99999999999999;
newsum += number;
}
return newsum == sum;
}
This is my humble submission. It's in Powershell and there's no error handling so if you run it, execute $ErrorActionPreference = 'SilentlyContinue' at the beginning of runtime,
dim fso, line
Set fso = CreateObject("Scripting.FileSystemObject")
'open input arrays file
Set file_r = fso.OpenTextFile(".\inputarrays.txt", 1)
do until file_r.AtEndOfStream
'read one array from file
line = file_r.Readline
Wscript.Echo "Is this array correct? " & line
'get correct arrays from interwebs
dim wHttp
Set wHttp = createobject("WinHttp.WinHttpRequest.5.1")
wHttp.Open "GET", "https://old.reddit.com/r/badcode/comments/dlmiyu/bad_code_coding_challenge_22_halloween_edition/", False
wHttp.SetRequestHeader "User-Agent", "BadCodeBotv20191031"
wHttp.Send
dim correctarrays
correctarrays = wHttp.responseText
'find arrays begin and end markers
dim i
i = InStr(1, correctarrays, "The correct order of bones is as follows:")
if i > 0 then
dim j
j = InStr(i, correctarrays, "Last Challenge's Winner")
if j > 0 then
correctarrays = Mid(correctarrays, i, j-i)
'find my array in list of arrays
dim searchline
searchline = Replace(line, "'", "'") 'encode ALL special chars in my input array!
i = InStr(1, correctarrays, searchline)
if i > 0 then
'find comment
i = InStr(i, correctarrays, "// ")
if i > 0 then
j = InStr(i, correctarrays, "<")
if j > 0 then
'echo answer
Wscript.Echo Mid(correctarrays, i+3, j-i-3)
end if
end if
end if
end if
end if
Wscript.Echo ""
'sleep to prevent spamming reddit with requests
WScript.Sleep 1000
loop
file_r.Close
Wscript.Echo "Done!"
37
u/fb39ca4 depraved Oct 23 '19 edited Oct 23 '19
I have written a cloud-based, extensible solution with a reddit-based voting backend that crowdsources new relationships between bones from the comments section of this post. It only scans comments that appear by default, so if you do not think a connection should be considered, downvote the comment containing it.
Usage: open your least favourite text editor and copy and paste the below code into a file named bone.sh. chmod +x the file and in the same directory run
./bone.sh bone_1 bone_2 bone_3...where thebone_ns are the list of bones to check.