Skip to content

Commit

Permalink
adding binary-search
Browse files Browse the repository at this point in the history
  • Loading branch information
kapitaali committed Apr 15, 2024
1 parent 581c08e commit fe44e42
Show file tree
Hide file tree
Showing 11 changed files with 679 additions and 0 deletions.
36 changes: 36 additions & 0 deletions exercises/practice/binary-search/.docs/instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# Instructions

Implement a binary search algorithm. Do not use any COBOL proprietary
search routines (eg. SEARCH).

Searching a sorted collection is a common task. A dictionary is a sorted
list of word definitions. Given a word, one can find its definition. A
telephone book is a sorted list of people's names, addresses, and
telephone numbers. Knowing someone's name allows one to quickly find
their telephone number and address.

If the list to be searched contains more than a few items (a dozen, say)
a binary search will require far fewer comparisons than a linear search,
but it imposes the requirement that the list be sorted.

In computer science, a binary search or half-interval search algorithm
finds the position of a specified input value (the search "key") within
an array sorted by key value.

In each step, the algorithm compares the search key value with the key
value of the middle element of the array.

If the keys match, then a matching element has been found and its index,
or position, is returned.

Otherwise, if the search key is less than the middle element's key, then
the algorithm repeats its action on the sub-array to the left of the
middle element or, if the search key is greater, on the sub-array to the
right.

If the remaining array to be searched is empty, then the key cannot be
found in the array and a special "not found" indication is returned.

A binary search halves the number of items to check with each iteration,
so locating an item (or determining its absence) takes logarithmic time.
A binary search is a dichotomic divide and conquer search algorithm.
35 changes: 35 additions & 0 deletions exercises/practice/binary-search/.docs/introduction.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Introduction

Implement a binary search algorithm.

Searching a sorted collection is a common task. A dictionary is a sorted
list of word definitions. Given a word, one can find its definition. A
telephone book is a sorted list of people's names, addresses, and
telephone numbers. Knowing someone's name allows one to quickly find
their telephone number and address.

If the list to be searched contains more than a few items (a dozen, say)
a binary search will require far fewer comparisons than a linear search,
but it imposes the requirement that the list be sorted.

In computer science, a binary search or half-interval search algorithm
finds the position of a specified input value (the search "key") within
an array sorted by key value.

In each step, the algorithm compares the search key value with the key
value of the middle element of the array.

If the keys match, then a matching element has been found and its index,
or position, is returned.

Otherwise, if the search key is less than the middle element's key, then
the algorithm repeats its action on the sub-array to the left of the
middle element or, if the search key is greater, on the sub-array to the
right.

If the remaining array to be searched is empty, then the key cannot be
found in the array and a special "not found" indication is returned.

A binary search halves the number of items to check with each iteration,
so locating an item (or determining its absence) takes logarithmic time.
A binary search is a dichotomic divide and conquer search algorithm.
23 changes: 23 additions & 0 deletions exercises/practice/binary-search/.meta/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"authors": [
"kapitaali"
],
"files": {
"solution": [
"src/binary-search.cob"
],
"test": [
"tst/binary-search/binary-search.cut"
],
"example": [
".meta/proof.ci.cob"
],
"invalidator": [
"test.sh",
"test.ps1"
]
},
"blurb": "Implement a binary search algorithm.",
"source": "Wikipedia",
"source_url": "http://en.wikipedia.org/wiki/Binary_search_algorithm"
}
99 changes: 99 additions & 0 deletions exercises/practice/binary-search/.meta/proof.ci.cob
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
IDENTIFICATION DIVISION.
PROGRAM-ID. BINARY-SEARCH.
AUTHOR. kapitaali.
ENVIRONMENT DIVISION.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 WS-ITEM PIC 9999.
01 WS-RESULT PIC 9999.
01 WS-ERROR PIC X(40) VALUE SPACES.
01 WS-ARRAY PIC X(60).
01 L PIC 99 VALUE 0.
01 R PIC 99.
01 M PIC 99.
01 STR PIC X(60).
01 EXP PIC 999 VALUE ZEROES.
01 IDX PIC 999.
01 NUM2 PIC ZZ9 VALUE ZEROES.
01 COUNTER PIC 999.
01 LEN PIC 999.

01 Teibel.
02 Taulukko PIC 999 OCCURS 1 TO 20
DEPENDING ON IDX.

PROCEDURE DIVISION.

STR-LENGTH.
MOVE 0 TO LEN.
PERFORM VARYING COUNTER FROM FUNCTION LENGTH(STR)
BY -1 UNTIL STR(COUNTER:1) <> " "
ADD 1 TO LEN
END-PERFORM.
COMPUTE LEN = FUNCTION LENGTH(STR) - LEN.


REVERSE-TABLE.
COMPUTE R = FUNCTION INTEGER-PART(IDX / 2).
PERFORM VARYING COUNTER FROM 1 BY 1 UNTIL COUNTER = R
COMPUTE L = IDX - COUNTER
MOVE Taulukko(L) TO NUM2
MOVE Taulukko(COUNTER) TO Taulukko(L)
MOVE NUM2 TO Taulukko(COUNTER)
END-PERFORM.


* populates the table from input string
MOVE-TO-TABLE.
MOVE WS-ARRAY TO STR.
PERFORM STR-LENGTH.
MOVE 20 TO IDX.
INITIALIZE Teibel.
MOVE 3 TO EXP.
MOVE 1 TO IDX
MOVE ZEROES TO NUM2.
PERFORM VARYING COUNTER FROM LEN BY -1 UNTIL COUNTER = 0
IF WS-ARRAY(COUNTER:1) = ','
MOVE 3 TO EXP
MOVE NUM2 TO Taulukko(IDX)
MOVE ZEROES TO NUM2
ADD 1 TO IDX
ELSE IF COUNTER = 1
MOVE WS-ARRAY(COUNTER:1) TO NUM2(EXP:1)
MOVE NUM2 TO Taulukko(IDX)
ADD 1 TO IDX
ELSE
MOVE WS-ARRAY(COUNTER:1) TO NUM2(EXP:1)
SUBTRACT 1 FROM EXP
END-IF
END-PERFORM.

* the actual algorithm
BINARY-SEARCH.
PERFORM MOVE-TO-TABLE.
IF IDX > 2
PERFORM REVERSE-TABLE
END-IF.
IF L IS LESS THAN 1 OR R IS GREATER THAN IDX
MOVE "value not in array" TO WS-ERROR
EXIT PARAGRAPH
END-IF.
MOVE 1 TO L.
COMPUTE R = IDX - 1.
PERFORM UNTIL L IS GREATER THAN R
COMPUTE M = L + R
COMPUTE M = FUNCTION INTEGER-PART(M / 2)
IF Taulukko(M) IS LESS THAN WS-ITEM
COMPUTE L = M + 1
ELSE IF Taulukko(M) IS GREATER THAN WS-ITEM
COMPUTE R = M - 1
ELSE
COMPUTE WS-RESULT = M - 1
IF Taulukko(WS-RESULT) = WS-ITEM
EXIT PARAGRAPH
ELSE
MOVE "value not in array" TO WS-ERROR
EXIT PARAGRAPH
END-IF
END-IF
END-PERFORM.
63 changes: 63 additions & 0 deletions exercises/practice/binary-search/bin/fetch-cobolcheck
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
#!/usr/bin/env bash

# This file is a copy of the
# https://github.com/exercism/configlet/blob/main/scripts/fetch-configlet file.
# Please submit bugfixes/improvements to the above file to ensure that all tracks benefit from the changes.

# set -eo pipefail

readonly LATEST='https://api.github.com/repos/0xE282B0/cobol-check/releases/latest'

case "$(uname)" in
Darwin*) os='mac' ;;
Linux*) os='linux' ;;
Windows*) os='windows' ;;
MINGW*) os='windows' ;;
MSYS_NT-*) os='windows' ;;
*) os='linux' ;;
esac

case "${os}" in
windows*) ext='.exe' ;;
*) ext='' ;;
esac

arch="$(uname -m)"

curlopts=(
--silent
--show-error
--fail
--location
--retry 3
)

if [[ -n "${GITHUB_TOKEN}" ]]; then
curlopts+=(--header "authorization: Bearer ${GITHUB_TOKEN}")
fi

suffix="${os}-${arch}${ext}"

get_download_url() {
curl "${curlopts[@]}" --header 'Accept: application/vnd.github.v3+json' "${LATEST}" |
grep "\"browser_download_url\": \".*/download/.*/cobol-check.*${suffix}\"$" |
cut -d'"' -f4
}

main() {
if [[ -d ./bin ]]; then
output_dir="./bin"
elif [[ $PWD == */bin ]]; then
output_dir="$PWD"
else
echo "Error: no ./bin directory found. This script should be ran from a repo root." >&2
return 1
fi

output_path="${output_dir}/cobolcheck${ext}"
download_url="$(get_download_url)"
curl "${curlopts[@]}" --output "${output_path}" "${download_url}"
chmod +x "${output_path}"
}

main
28 changes: 28 additions & 0 deletions exercises/practice/binary-search/bin/fetch-cobolcheck.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# This file is a copy of the
# https://github.com/exercism/configlet/blob/main/scripts/fetch-configlet.ps1 file.
# Please submit bugfixes/improvements to the above file to ensure that all tracks
# benefit from the changes.

$ErrorActionPreference = "Stop"
$ProgressPreference = "SilentlyContinue"

$requestOpts = @{
Headers = If ($env:GITHUB_TOKEN) { @{ Authorization = "Bearer ${env:GITHUB_TOKEN}" } } Else { @{ } }
MaximumRetryCount = 3
RetryIntervalSec = 1
}

$arch = If ([Environment]::Is64BitOperatingSystem) { "amd64" } Else { "x86" }
$fileName = "cobol-check-windows-$arch.exe"

Function Get-DownloadUrl {
$latestUrl = "https://api.github.com/repos/0xE282B0/cobol-check/releases/latest"
Invoke-RestMethod -Uri $latestUrl -PreserveAuthorizationOnRedirect @requestOpts
| Select-Object -ExpandProperty assets
| Where-Object { $_.browser_download_url -match $FileName }
| Select-Object -ExpandProperty browser_download_url
}

$downloadUrl = Get-DownloadUrl
$outputFile = Join-Path -Path $PSScriptRoot -ChildPath "cobolcheck.exe"
Invoke-WebRequest -Uri $downloadUrl -OutFile $outputFile @requestOpts
Loading

0 comments on commit fe44e42

Please sign in to comment.