This is a project for a code challenge:
Write a program in whatever language you prefer that takes an array of integers and decides whether those integers conform to Benford's Law.
This project was written in PHP 7.4. It exists within a bare-bones RESTful API mini-framework that I previously wrote for testing sample code through Postman HTTP requests.
The margin of error
is calculated for each distribution of a leading digit (1-9). If the actual distribution percentage
is within the expected distribution percentage
plus or minus the margin of error
, the assumption is made that the distribution of that leading digit conforms to Benford's law.
- Environment variables go into
/config/.env
and newly-required.env
definitions are checked into/config/bootstrap.php
- Routes for all endpoints are declared in
/public/index.php
- PSR4 namespacing is used in the
src
directory for all other project-related files- e.g., The
Davidwyly\Pronto\Http\Controller\TestController
class is located at/src/Davidwyly/Pronto/Http/Controller/TestController.php
- e.g., The
- Tests are located in
/tests
- Test fixtures in
/tests/fixtures
- Mock objects are located in
/src/Davidwyly/Pronto/Mock
- Test fixtures in
While this project does not have to be installed in order to be evaluated, I have set up docker so that you can more easily run and test the service yourself.
These installation instructions assume that the following is already installed on your dev environment:
- Git
- Composer
- Docker
- Docker Compose
- Postman
- Navigate to your home directory
cd ~
- Clone down the project
git clone git@github.com:davidwyly/pronto
- Ensure you're in the root directory
cd ~/pronto
- Run
source .bash_aliases
- To view all alias commands for this project, run
cat .bash_aliases
- Ensure you're in the root directory
cd ~/pronto
- Composer install
composer install
- Open up a new terminal
- Navigate to the root directory
cd ~/pronto
- Build your containers
docker-compose up --build
- Ensure you're in the root directory
cd ~/pronto
- Run the PHPUnit tests
run_tests
- Import collection from
~/pronto/storage/Pronto.postman_collection.json
- Set up a new postman environment
- Click the gear icon in top-right corner
- Click
Add
- Create an environment name
- Add a
url
variable withlocalhost:8080
as the initial value - Click
Add
- Select the environment from the drop-down in the top-right corner
- Requests can be found within the
Pronto
collection
{
"sample-size": 1000,
"z-score": 0.4621525165147706,
"standard-deviation": 2.460911840575985,
"1": {
"expected": "30.103%",
"actual": "30.1%",
"variance": "-0.003%",
"margin-of-error": "0.6704%",
"conforms-to-benford's-law": true
},
"2": {
"expected": "17.6091%",
"actual": "17.7%",
"variance": "0.0909%",
"margin-of-error": "0.5578%",
"conforms-to-benford's-law": true
},
"3": {
"expected": "12.4939%",
"actual": "12.5%",
"variance": "0.0061%",
"margin-of-error": "0.4833%",
"conforms-to-benford's-law": true
},
"4": {
"expected": "9.691%",
"actual": "9.6%",
"variance": "-0.091%",
"margin-of-error": "0.4305%",
"conforms-to-benford's-law": true
},
"5": {
"expected": "7.9181%",
"actual": "8%",
"variance": "0.0819%",
"margin-of-error": "0.3965%",
"conforms-to-benford's-law": true
},
"6": {
"expected": "6.6947%",
"actual": "6.7%",
"variance": "0.0053%",
"margin-of-error": "0.3654%",
"conforms-to-benford's-law": true
},
"7": {
"expected": "5.7992%",
"actual": "5.6%",
"variance": "-0.1992%",
"margin-of-error": "0.336%",
"conforms-to-benford's-law": true
},
"8": {
"expected": "5.1153%",
"actual": "5.3%",
"variance": "0.1847%",
"margin-of-error": "0.3274%",
"conforms-to-benford's-law": true
},
"9": {
"expected": "4.5757%",
"actual": "4.5%",
"variance": "-0.0757%",
"margin-of-error": "0.303%",
"conforms-to-benford's-law": true
}
}
{
"sample-size": 505,
"z-score": 1.6379464099227126,
"standard-deviation": 2.1521345609224443,
"1": {
"expected": "30.103%",
"actual": "14.2574%",
"variance": "-15.8456%",
"margin-of-error": "2.5484%",
"conforms-to-benford's-law": false
},
"2": {
"expected": "17.6091%",
"actual": "23.7624%",
"variance": "6.1533%",
"margin-of-error": "3.1023%",
"conforms-to-benford's-law": false
},
"3": {
"expected": "12.4939%",
"actual": "19.2079%",
"variance": "6.714%",
"margin-of-error": "2.8713%",
"conforms-to-benford's-law": false
},
"4": {
"expected": "9.691%",
"actual": "0%",
"variance": "-9.691%",
"margin-of-error": "0%",
"conforms-to-benford's-law": false
},
"5": {
"expected": "7.9181%",
"actual": "14.2574%",
"variance": "6.3393%",
"margin-of-error": "2.5484%",
"conforms-to-benford's-law": false
},
"6": {
"expected": "6.6947%",
"actual": "9.505%",
"variance": "2.8103%",
"margin-of-error": "2.1377%",
"conforms-to-benford's-law": false
},
"7": {
"expected": "5.7992%",
"actual": "19.0099%",
"variance": "13.2107%",
"margin-of-error": "2.86%",
"conforms-to-benford's-law": false
},
"8": {
"expected": "5.1153%",
"actual": "0%",
"variance": "-5.1153%",
"margin-of-error": "0%",
"conforms-to-benford's-law": false
},
"9": {
"expected": "4.5757%",
"actual": "0%",
"variance": "-4.5757%",
"margin-of-error": "0%",
"conforms-to-benford's-law": false
}
}