Installing Webmin on CentOS 7 and configure firewall

Some days ago I described the steps involved in configuring a CentOS WebServer VM with virtual hosts here manually. In this post I will describe the steps involved to install Webmin .

Creating a repository file for Webmin

cd /etc/yum.repos.d/

sudo vi webmin.repo
[Webmin]
name=Webmin Distribution Neutral
#baseurl=http://download.webmin.com/download/yum
mirrorlist=http://download.webmin.com/download/yum/mirrorlist
enabled=1
Esc
:wq

Install Webmin GPG key

rpm --import http://www.webmin.com/jcameron-key.asc

Update Repositories

yum check-update
Update Repos
Update Repos

Install Webmin

yum -y install webmin

Add to startup

chkconfig webmin on

Start the service

service webmin start

Enable webmin port in firewall

firewall-cmd --permanent --add-port=10000/tcp
firewall-cmd --reload

 

Open in browser

https://192.168.101.39:10000/ where 192.169.101.39 is your VM IP (ip addr)

 

Trust and Add
Trust and Add
Add exception
Add exception
Webmin Login
Webmin Login

 

Use same credentials used to admin the VM

Webmin Dashboard
Webmin Dashboard

 

 

Creating REST API Example with Laravel 5

This walkthrough should work on a VM described here

Assuming Database configuration is already set

in app/config/database.php or .env file

cd /var/www/dev1.local/laravel

Create Database Migration

In this example I decided to create a Courses table

php artisan make:migration create_courses_table --create=courses

Database Migration
Database Migration

 

Navigate with SFTP to /var/www/dev1.local/laravel/database/migrations

Edit the created file 2015_11_10_152128_create_courses_table.php and add the required fields.

Create Courses Table Migration file
Create Courses Table Migration file

 

Adding fields for example, Course name, Classroom, Teacher

$table->string(‘course_name’);
$table->string(‘classroom’);
$table->string(‘teacher’);

Adding Fields to migration
Adding Fields to migration

 

Migrating tables to MariaDB
Migrating tables to MariaDB
Database in SQLyog
Database in SQLyog

 

Create Models folder in  /var/www/dev1.local/laravel/app

mkdir /var/www/dev1.local/laravel/app/Models

Create Course Model

sudo vi  mkdir /var/www/dev1.local/laravel/app/Models/Course.php

Course Model
Course Model

 

Seeding the Database

cd /var/www/dev1.local/laravel/database/seeds

sudo vi CoursestTableSeeder.php

Courses Database Seeder
Courses Database Seeder

 

vi /var/www/dev1.local/laravel/database/seeds/DatabaseSeeder.php

Register CourseDatabaseSeeder
Register CourseDatabaseSeeder

 

composer dump-autoload

php artisan clear-compiled

Run php artisan db:seed

Seeding the database
Seeding the database SQLyog
Seeded data in database
Seeded data in database

Course Controller

php artisan make:controller CourseController

Creating a Controller for Courses
Creating a Controller for Courses

 

sudo vi /var/www/dev1.local/laravel/app/Http/Controllers/CourseController.php

Generated Controller Stub
Generated Controller Stub

 

Implementing the Controller

Add the following uses at the top

use DB;
use Response;
use Input;
use App\Models\Course;

Implementing some of the actions. Index, Store, Show, Delete

public function index()
{
return Response::json(Course::get());
}

public function store()
{
Course::create(array(
‘teacher’ => Input::get(‘teacher’),
‘classroom’ => Input::get(‘classroom’),
‘course_name’ => Input::get(‘course_name’)
));
return Response::json(array(‘success’ => true));
}

public function show($id)
{
$course = Course::find($id);
if(!isset($course)){
return $this->respondNotFound(‘Course does not exist’);
}
return $this->respond([
‘data’ => $this->transform($course)
]);
}

Creating Routes

sudo vi /var/www/dev1.local/laravel/app/Http/routes.php

Add

Route::group([‘prefix’ => ‘/api/v1’], function()
{
Route::resource(‘course’, ‘CourseController’ );
});

save and execute

php artisan route:list

Laravel Routes
Laravel Routes

Testing the API

http://dev1.local/index.php/api/v1/courses

or

http://dev1.local/api/v1/courses

API test
API test

 

Next Post is about Creating Angular based Front-end to consume the above API

Installing CentOS 7, Configuring Virtual Hosts and install Laravel 5 on each host

Download CentOS 7 ISO file mount it and create a VM in Virtualbox and boot

Select the following:

  • Simple webserver
  • PHP

yum install php-common

Open Firewall for Apache and register as service

firewall-cmd –permanent –add-service=http

firewall-cmd –reload

sudo systemctl enable httpd

Install MariaDB and register as service

Check if installed

rpm -qa | grep mariadb

yum install mariadb-server

sudo systemctl enable mariadb.service

mysql

> grant all on *.* to ‘sgalea’@’%’ identified by ‘bitnami’ with grant option;

quit

 

sudo vi /etc/my.cnf

[mysqld]

skip-grant-tables

 

Enable External connections to the database

firewall-cmd –permanent –add-service=mysql

firewall-cmd –reload

 

yum -y install php-mysql

 

Install SFTP and enable as service

yum -y update

yum -y install vsftpd

Conf location: /etc/vsftpd/vsftpd.conf

sudo systemctl enable vsftpd

firewall-cmd –permanent –add-port=21/tcp

firewall-cmd –reload

 

Creating Virtual Hosts Settings

mkdir /etc/httpd/sites-available

mkdir /etc/httpd/sites-enabled

sudo vi /etc/httpd/conf/httpd.conf

Put the following at the end of file

IncludeOptional sites-enabled/*.conf

Esc :wq

Create a file per virtual host in /etc/httpd/sites-available

sudo vi /etc/httpd/sites-available/dev1.local.conf

<VirtualHost *:80>
ServerName  dev1.local
ServerAlias dev1.local
DocumentRoot /var/www/dev1.local/laravel/public
ErrorLog /var/www/dev1.local/logs/error.log
CustomLog /var/www/dev1.local/logs/requests.log combined
</VirtualHost>

sudo vi /etc/httpd/sites-available/dev2.local.conf

<VirtualHost *:80>
ServerName  dev2.local
ServerAlias dev2.local
DocumentRoot /var/www/dev2.local/laravel/public
ErrorLog /var/www/dev2.local/logs/error.log
CustomLog /var/www/dev2.local/logs/requests.log combined
</VirtualHost>

sudo vi /etc/httpd/sites-available/dev3.local.conf

<VirtualHost *:80>
ServerName  dev3.local
ServerAlias dev3.local
DocumentRoot /var/www/dev3.local/laravel/public
ErrorLog /var/www/dev3.local/logs/error.log
CustomLog /var/www/dev3.local/logs/requests.log combined
</VirtualHost>

https://www.digitalocean.com/community/tutorials/how-to-set-up-apache-virtual-hosts-on-centos-7

Enabling the hosts

sudo ln -s /etc/httpd/sites-available/dev1.local.conf /etc/httpd/sites-enabled/dev1.local.conf
sudo ln -s /etc/httpd/sites-available/dev2.local.conf /etc/httpd/sites-enabled/dev2.local.conf
sudo ln -s /etc/httpd/sites-available/dev3.local.conf /etc/httpd/sites-enabled/dev3.local.conf

Create folders

mkdir /var/www/dev1.local

mkdir /var/www/dev2.local

mkdir /var/www/dev3.local

sudo chmod -R 775 /var/www

Install Composer Globally

curl -sS https://getcomposer.org/installer | php
mv composer.phar /usr/local/bin/composer

Install Laravel Dependencies

ext-mbstring
sudo yum install php-mbstring

ext-mcrypt

wget http://dl.fedoraproject.org/pub/epel/7/x86_64/e/epel-release-7-5.noarch.rpm

rpm -ivh epel-release-7-5.noarch.rpm

yum install php-mcrypt*

Install Laravel

navigate to the folder where one wishes to install it in my case

cd /var/www/dev1.local
composer create-project laravel/laravel –prefer-dist

cd /var/www/dev2.local
composer create-project laravel/laravel –prefer-dist

cd /var/www/dev3.local
composer create-project laravel/laravel –prefer-dist

 

Storage Folder needs write permissions in SELinux

su -c "chcon -R -h -t httpd_sys_script_rw_t /var/www/dev1.local/laravel/storage/"

su -c "chcon -R -h -t httpd_sys_script_rw_t /var/www/dev2.local/laravel/storage/"

su -c "chcon -R -h -t httpd_sys_script_rw_t /var/www/dev3.local/laravel/storage/"

chmod -R 777 /var/www/dev1.local/laravel/storage/

chmod -R 777 /var/www/dev2.local/laravel/storage/

chmod -R 777 /var/www/dev3.local/laravel/storage/

  • Not sure if 777 is a good idea here

We need a location for logs

mkdir /var/www/dev1.local/logs

su -c "chcon -R -h -t httpd_sys_script_rw_t /var/www/dev1.local/logs/"

mkdir /var/www/dev2.local/logs

su -c "chcon -R -h -t httpd_sys_script_rw_t /var/www/dev2.local/logs/"

mkdir /var/www/dev3.local/logs

su -c "chcon -R -h -t httpd_sys_script_rw_t /var/www/dev3.local/logs/"

 

sudo systemctl restart httpd.service

Check virtualhosts

httpd -S

Add virtual hosts in host file on your host OS

On windows: C:\Windows\System32\drivers\etc

edit host file as Administrator

192.168.101.12 dev1.local
192.168.101.12 dev2.local
192.168.101.12 dev3.local

Where 192.168.101.12 is the IP of your Virtual Machine running CentOS 7

Remove index.php from the url

sudo vi /etc/httpd/conf/httpd.conf

AllowOverride Access
AllowOverride Access

Change to:

AllowOverride All

 

Things required while debugging issues:

While debugging try without SELinux

Disable:

setenforce 0

Enable:

setenforce 1

These are not permanent they will be reset to default status after reboot.

Search string in file

grep -R ‘string’ dir/

Find IP

ip addr

Changing IP of the VM

sudo dhclient -r

sudo dhclient

__________________________________________________________________

http://stackoverflow.com/questions/17954625/services-json-failed-to-open-stream-permission-denied-in-laravel-4

Errorlogs location causes htttpd not reload

http://unix.stackexchange.com/questions/175558/apache-wont-restart-after-adding-virtualhost-conf-file-why-not

Blankscreen issue

http://stackoverflow.com/questions/20678360/laravel-blank-white-screen

ServerSetup

http://www.hexblot.com/blog/centos-7-server-installation

 

Next Post is about creating a REST API on Laravel 5 which can be found here

Configuring Laravel 5, FTP and MySQL on Bitnami LAMP Stack for Development

At the time of writing the Stack is running on Ubuntu 14.04 which can be downloaded from here. Since it is 64Bit make sure that Visualization is enabled in the bios settings.

Import the VM in VMware Player or Virtual box, make sure that the network settings are configured correctly so that the VM gets an IP accessible from the host machine. I personally configured it to Bridged Adapter for this exercise and have a habit of Regenerating the MAC Address.

VirtualBox Network Adapter Setup
VirtualBox Network Adapter Setup

If the VM does not get assigned an IP the configuration is wrong and I wouldn’t bother trying to fix it from inside the VM (you could) but I rather fix it from the hyper-visor settings because the stack is pre-configured to work.

Bitnami LAMP Stack with indication of IP
Bitnami LAMP Stack with indication of IP

Login and change password

 

Visit the IP in the browser to check if it is working in my case http://192.168.101.12

Bitnami Main Page
Bitnami Main Page

 

Enabling Laravel

Bitnami LAMP Stack comes with several pre-configured frameworks of which all are disabled by default. One must enable the framework that is required. ( I am nto sure if you can enable more than one at the same time)

Steps:

cd /opt/bitnami/apache2/conf/bitnami

sudo vi bitnami-apps-prefix.conf

Accessing LAMP PHP Framework Config
Accessing LAMP PHP Framework Config

 

Remove the hash from laravel’s line and save and close :wq

Enabling Laravel
Enabling Laravel

 

Restart Apache

sudo /opt/bitnami/ctlscript.sh restart apache

Restarting Apache
Restarting Apache

 

The location where Laravel apps Live is

/opt/bitnami/frameworks/laravel/app/http

Browser URL

http://192.168.101.12/laravel/ where 192.168.101.12 is your VM’s IP

 

Laravel Welcome Screen On Load
Laravel Welcome Screen On Load

 

Configuring FTP

Enabling FTP for easy editing/upload of files ( Note this is a development machine for experimentation so I will not go on explaining issues with FTP and security, but you should consider reading about the risks. )

 

sudo vi /etc/vsftpd.conf

go to the bottom of the file and change

listen_address=127.0.0.1

to

listen_address=0.0.0.0

:wq

Listen on every available network interface
Listen on every available network interface

Allow connections to port 21 (FTP port)

sudo ufw allow 21

Firewall Settings
Firewall Settings

Restart FTP

sudo service vsftpd restart

Restart vsftpd service
Restart vsftpd service

Change bitnamiftp password

sudo passwd bitnamiftp

Change Password for FTP user
Change Password for FTP user

Configure Filezilla

Filezilla FTP Settings
Filezilla FTP Settings

Connected

Connected to VM
Connected to VM

 

Now you may play around with Laravel through FTP 🙂

Let external connections to MySQL

1)

cd /opt/bitnami/mysql

sudo vi my.cnf

Comment out

bind-address = 127.0.0.1

by putting a # infront of it and Esc :wq

Modifying my.cnf to allow external connections
Modifying my.cnf to allow external connections

2)

 

mysql -u root -p
grant all privileges on *.* to 'root'@'%' identified by 'password' with grant option
Granting MySQL Permissions
Granting MySQL Permissions

 

restart mysql

cd /opt/bitnami

sudo ./ctlscript.sh restart mysql

Restart MySQL
Restart MySQL

 

Open Port in firewall

sudo ufw allow 3306

Open port 3306 in firewall
Open port 3306 in firewall

 

Connection Settings in SQLyog
Connection Settings in SQLyog

 

Connection Successful
Connection Successful

HOB Software Competition

For their 25th anniversary HOB Software decided to have a Problem Solving competition

 

1

2

I was at work and decided to give it a go during the break. After decompressing the HSM Problem solving Competition.rar6

Stage 1:

I opened the raw class file in vim and noticed something interesting

7

<p style=”font-size:110%”><b>Stage 2: U3RhZ2UgMzogNTMgNzQgNjEgNjcgNjUgMjAgMzQgM2EgMjAgMzEgMzMgMzQgMzcgMzcgMzcgMzMgMzcgMzUgMzY=</b></p>

To me this seemed like a base64 encoded string prefixed with Stage 2: meant I somehow solved the first Stage. Not being satisfied I decided to decompile the class back to java which produced the following code:

import Main;
import java.awt.Color;
import java.awt.Component;
import java.awt.GridBagLayout;
import java.awt.LayoutManager;
import java.io.File;
import java.net.URL;
import java.security.CodeSource;
import java.security.ProtectionDomain;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextPane;
import javax.swing.border.Border;

public class Competition
extends JFrame {
final String gz = "STAGE 1 COMPLETE! 4 STAGES LEFT!";
private static final long serialVersionUID = 1;
private String gotostage2dottxt = "gotostage2.txt";
private JTextPane label;

public Competition() {
super("HOB Software Malta Competition");
this.setDefaultCloseOperation(3);
this.setLayout(new GridBagLayout());
this.label = new JTextPane();
this.label.setEditable(false);
this.label.setBackground(null);
this.label.setBorder(null);
this.label.setContentType("text/html");
File file = new File(String.valueOf(this.getExecutableLocation()) + this.gotostage2dottxt);
if (file.exists() && !file.isDirectory()) {
this.doTextFilePresentProcedure();
this.setSize(1000, 200);
} else {
this.doTextFileAbsentProcedure();
this.setSize(600, 200);
}
this.setLocationRelativeTo(null);
this.setVisible(true);
}

String getExecutableLocation() {
return Main.class.getProtectionDomain().getCodeSource().getLocation().getPath().replaceAll("%20", " ");
}

void doTextFilePresentProcedure() {
this.label.setText("<p style=\"font-size:110%\"><b>Stage 2: U3RhZ2UgMzogNTMgNzQgNjEgNjcgNjUgMjAgMzQgM2EgMjAgMzEgMzMgMzQgMzcgMzcgMzcgMzMgMzcgMzUgMzY=</b></p>");
JPanel panel1 = new JPanel(new GridBagLayout());
panel1.add(this.label);
this.add(panel1);
}

void doTextFileAbsentProcedure() {
this.label.setText("<p style=\"font-size:150%\"><b>404 - File Not Found</b></p>");
JPanel panel1 = new JPanel(new GridBagLayout());
panel1.add(this.label);
this.add(panel1);
}
}

There is a conditional looking for a file named gotostage2.txt, so in reality the first stage was to create an empty text file named gotostage2.txt and execute the run_me.bat.

3

another fact seems like that from “STAGE 1 COMPLETE! 4 STAGES LEFT!” this competition has 5 stages.

Stage 2:

https://www.base64decode.org/

4

U3RhZ2UgMzogNTMgNzQgNjEgNjcgNjUgMjAgMzQgM2EgMjAgMzEgMzMgMzQgMzcgMzcgMzcgMzMgMzcgMzUgMzY=

Stage 3: 53 74 61 67 65 20 34 3a 20 31 33 34 37 37 37 33 37 35 36

 

Stage 3:

http://www.rapidtables.com/convert/number/hex-to-ascii.htm

53 74 61 67 65 20 34 3a 20 31 33 34 37 37 37 33 37 35 36

5

Stage 4: 1347773756

Stage 4:

1347773756

 

I tried a lot of things including trying to map the numbers to letters on the phone keypad but yielded no success.

Stuck here!!

 

Stage 5:

??

JavaScript BreakOut

A couple of weeks ago I was playing around with canvas for the first time I decided to give a try in recreating a BreakOut like game using JavaScript.

The game is developed using Object Oriented approach for better structure and the code is easier to handle.

I found that using multiple canvas with some CSS to overlay them is a better approach to minimize computations and separate things.

Breakout
Breakout

 

 

It is unfinished let alone polished.

Can be viewed at JSFiddle: here

Things missing

  • Menu
  • Ball moving with paddle before start
  • Instructions of play ( Left/Right/Space )
  • Score Keeping
  • Game calculations could be better
  • Level transition although loading mechanism is in place and levels can be described in JSON format.

Might get back to it at some point, but right now I’m working on something else.

CodingChillout.Malta

Sphere contest    Last week it was the first of which I took part and landed at 2nd place on the leader board

 

POS 1 2 3
NAME Peng Cao Fairmutex Javi
TEST1.00 1.00 (1) 1.00 (1) 1.00 (1)
FCTRL21.00 1.00 (17) 1.00 (1) 1.00 (1)
ADDTWO1.00 1.00 (24) 1.00 (1) 1.00 (1)
REVARR1.00 1.00 (1) 1.00 (1) 1.00 (1)
PREFSUFF10.00 10.00 (7) 10.00 (2) 10.00 (14)
CONVERT50.00 50.00 (9) 50.00 (11) 50.00 (5)
GLUTTONS5.00 5.00 (1) 5.00 (1) 5.00 (10)
HTMLTAGS25.00 25.00 (1) 25.00 (1) 25.00 (1)
LADYBUGS80.00 80.00 (1) 72.00 (3) 64.00 (4)
SOL 9 9 9
SCORE 174 166 158

The questions ranged from very easy to ones that required some thinking

http://codechillout.sphere-contest.com/ranking

Winners announced on twitter

I will try to post about the Challenges and how I tackled them soon.

Warm-up session

TEST ( c99 strict )
Small factorials ( Python 2.7 )
Add two number ( Python 2.7 )
Reverse Array ( Python 2.7 )

Online Round

Prefix-suffix balance ( c99 strict )
Simple Numbers Conversion (Python 2.7)
Gluttons (Java 7/Python 2.7 / c99 strict )
Ladybugs race (c99 strict)
HTML tags (Python 2.7)

http://codechillout.sphere-contest.com/

 

CodingChillout.Malta: Prefix-suffix balance

http://codechillout.sphere-contest.com/problems/onlineround/PREFSUFF

Prefix-suffix balance

One of the most popular problems presented during the initial stages of IT recruitment is that of finding a place in a sequence of integers which divides it into two groups of equal sum, i.e., at a position where the sum of the prefix is equal to the sum of the suffix. Your task is to find this position.

Input

The first line contains exactly one number t, representing the number of data sets. Each data set i is a single line, consisting of the sequence length mi and exactly mi integers which form the sequence. Numbers in data sets are separated by spaces.

Output

For each data set i print the shortest possible length of the prefix for which the sum of elements is equal to the sum of elements of the determined suffix. If desired number does not exist, then print 0. Answers for data sets should be separated by new lines.

Notes

The prefix and suffix cannot be empty.

Example

Input:
4
5 4 2 3 1 2
5 4 -2 1 1 -2
6 1 -1 1 -1 1 -1
3 0 0 0

Output:
2
0
2
1

 

Answer

#include 

int main(void) {
	int instances;
	scanf("%d", &instances);
	int n;
	int i;
	for(i = 0 ; i < instances ; i++){
		scanf("%d", &n);
		int entries[n];
		int j;
		for(j = 0 ; j < n ; j++){
			scanf("%d", &entries[j]);
		}
		int sumA[n-1];
    	int total = 0;
    	int k;
    	int flag1 =1;
    	for(k = 0 ; k <= n-2 ; k++){
    		if(entries[k] != entries[n-(k)]) // Check for palindrome
    		     flag1=0;
	    	total +=entries[k];
	    	sumA[k] = total;
    	}
    	if(flag1 == 1 && entries[n/2] == entries[(n/2)-1])
    	    return (n/2)-1;
    	
	    total +=entries[n-1];
	    int flag = 1;
        if(total%2 == 0){ // If it is odd it cannot be split
        	int j;
        	int tot2 = total/2;
	    	for(j = 0 ; j <= n-2 ; j++){
		      if(sumA[j] == tot2){
		         printf("%d\n", j+1);
		         flag = 0;
		         break;
		      }
		    }
        }
       if(flag ==1)
          printf("0\n");
	}
	return 0;
}

CodingChillout.Malta: Warm-up Session

Warm-Up round at Codingchillout.Malta http://codechillout.sphere-contest.com/round/test

http://codechillout.sphere-contest.com/problems/test/TEST

TEST

Your program is to use the brute-force approach in order to find the Answer to Life, the Universe, and Everything. More precisely… rewrite small numbers from input to output. Stop processing input after reading in the number 42. All numbers at input are integers of one or two digits.

Example

Input:
1
2
88
42
99

Output:
1
2
88

Answer

#include 

int main(void) {
	int i;
	while (scanf("%d", &i)==1){
		if(i == 42) break;
		printf("%d\n",i);
	}

	return 0;
}

http://codechillout.sphere-contest.com/problems/test/FCTRL2

Small factorials

You are asked to calculate factorials of some small positive integers.

Input

An integer t, 1<=t<=100, denoting the number of testcases, followed by t lines, each containing a single integer n, 1<=n<=100.

Output

For each integer n given at input, display a line with the value of n! (“n factorial”).

Example

Sample input:

4
1
2
5
3

Sample output:

1
2
120
6

Answer

import math

n = int(raw_input());
for v in range(0,n):
	print math.factorial(int(raw_input()))

http://codechillout.sphere-contest.com/problems/test/ADDTWO

Add two number

Calculate the sum a+b for given integers a and b.

Input

There will be provided certain number of data sets for the problem. Each data set consist of two integer numbers ai and bi separated with a space, where i is the number of the data set. Data sets are separated with a new line.

Output

For ith data set print the value of ai + bi. Answers should be separated with a new line.

Example

Input:
2 3
10 -2
-1 5
-3 -3
0 1

Output:
5
8
4
-6
1

Answer

import fileinput

for line in fileinput.input():
    n = line.split();
    print int(n[0]) + int(n[1])

http://codechillout.sphere-contest.com/problems/test/REVARR

Reverse array

For a given array reverse its order.

Input

In the first line there will be a number of the data sets t. In the next t lines data sets follows. Each data set is a line of numbers separated by spaces. First number ni is the length of the array. Next ni numbers are the values in array.

Output

For ith data set write values from array in reversed order. Numbers should be separated by spaces and answers for data sets should be separated by a new line.

Example

Input:
2
7 1 2 3 4 5 6 7
3 3 2 11

Output:
7 6 5 4 3 2 1
11 2 3

Answer

n = int(raw_input())
for v in range(0,n):
    j = raw_input().split(" ")
    del j[0]
    j = " ".join(reversed(j))
    print j

CodingChillout.Malta: Gluttons

http://codechillout.sphere-contest.com/problems/onlineround/GLUTTONS

Gluttons

Every year Megabyteland hosts The Great Gluttony Festival. According to tradition, during the first day of the festival all participants eat cookies nonstop for 24 hours (with not even a fraction of a second’s break!). As soon as a glutton has finished eating one cookie, he immediately stars to eat the next one (this does not apply only to the situation at the end of the day, when the participant is not allowed to start eating a cookie if he knows that he cannot finish eating it before the end of the day). Another important part of the tradition is that each glutton eats a single cookie at his very own constant characteristic pace.

For the coming festival, the organizers have invited only those gluttons who have already participated in the previous editions. This means that the pace of each glutton is already known (they don’t really like to change their natural pace). Based on this data, the organizers of the festival want to determine how many cookies they need to buy. However, the cookies in the shop are sold in boxes of fixed size, thus they may have to buy more cookies than the number that is going to be eaten.

Your task is to establish the number of boxes with cookies that are needed to carry out the competition. The number of participants, along with the pace of each of them (given in seconds needed to eat a single cookie) will be given.

Input

The first line of input contains the number of test cases t. Each test case has the following form: two numbers N and M, separated by a space, in the first line (1 ≤ N ≤ 10000, 1 ≤ M ≤ 1000000000). The first number N is the number of invited gluttons and the second number M is the numbers of cookies in the box. Each line of the next N lines contains a single integer number, representing the pace of the glutton. The pace of the glutton is expressed as the number of seconds (not greater than 100000) needed to eat a single cookie.

Output

For each test case you need to write exactly one integer denoting the number of boxes which have to be bought by the organizers to carry out the contest. Answers for distinct test cases should be written in separate lines.

Example

Input:
2
2 10
3600
1800
3 356
123
32999
10101

Output:
8
2

Answers

C

#include 
#include 
int main(void) {
	int n;
	int invites;
	int nBox;
	int i;
	scanf("%d", &n);
	for(i = 0 ; i < n ; i++){
		scanf("%d %d", &invites,&nBox);
	    double total = 0;
		int j;
		for(j = 0 ; j < invites;j++){
			    int time;
			    scanf("%d",&time);
		    	total += 86400/time;
        }
        printf("%d\n",(int)ceil(total/nBox));
	}
	return 0;

Python 2.7

import math
contestDuration = 86400
instances = int(raw_input())
for v in range(0,instances):
    data = raw_input().split(" ") # Invited/Cookies
    i = int(data[0])
    cookies = int(data[1])
    total = 0
    for k in range(0,i):
       total = total + contestDuration/int(raw_input())
    print int(math.ceil(total/cookies))

Java 7

import java.util.*;
import java.lang.*;

class Main
{
	public static void main (String[] args) throws java.lang.Exception
	{
		 java.io.BufferedReader r = new java.io.BufferedReader (new java.io.InputStreamReader (System.in));
		 int instances = Integer.parseInt(r.readLine());
		 
		 for(int k = 0 ; k < instances; k++){
		    String [] data = r.readLine().split("\\s+");
		    int invites = Integer.parseInt(data[0]);
		    double total = 0;
		    for(int i = 0 ; i < invites; i++){
		    	total += 86400/Integer.parseInt(r.readLine());
		 
		    }
		    System.out.println((int)Math.ceil(total/Integer.parseInt(data[1])));
		 }
	}
}