I'm using zxing to generate an EAN13 barcode. Everything works fine when I use this code:
new EAN13Writer().encode(eanValue, BarcodeFormat.EAN_13, requestedWidth, requestedHeight);
Result:
Now, the customer wants to have a lead, separater and a trailer like this one:
(Image source)
As far as I understand the code of zxing (see here) I'm using above can't make those lines longer than others. But I've found out that there are two encode-methods in the EAN13Writer and it seems like, the second encode-function does exactly what I want to do. But the problem is that this function doesn't return a bitmatrix but a boolean array. (Edit: Nope the function does not achieve what I want to do)
Can anybody tell me how I can achieve the second barcode style?
As I couldn't find a solution in the zxing code I wrote my own EAN13Writer. I had to copy paste some methods and constants as they were package-private in the zxing package.
Basically it just stores the position of the lines which shall be longer in a member variable. When the BitMatrix is rendered every line which should not be longer will be shortened by 5%. If anybody has the same problem this code might help a little bit.
/**
* This is a custom implementation as the customer wants a modified barcode with longer and shorter lines for start, middle and end.
* Most code is based on Code from the OneDimensionalCodeWriter, EAN13Writer and UPCEANReader but
* had to be copied as the methods were package private
*
*/
public class CustomEAN13Writer extends OneDimensionalCodeWriter {
// For an EAN-13 barcode, the first digit is represented by the parities used
// to encode the next six digits, according to the table below. For example,
// if the barcode is 5 123456 789012 then the value of the first digit is
// signified by using odd for '1', even for '2', even for '3', odd for '4',
// odd for '5', and even for '6'. See http://en.wikipedia.org/wiki/EAN-13
//
// Parity of next 6 digits
// Digit 0 1 2 3 4 5
// 0 Odd Odd Odd Odd Odd Odd
// 1 Odd Odd Even Odd Even Even
// 2 Odd Odd Even Even Odd Even
// 3 Odd Odd Even Even Even Odd
// 4 Odd Even Odd Odd Even Even
// 5 Odd Even Even Odd Odd Even
// 6 Odd Even Even Even Odd Odd
// 7 Odd Even Odd Even Odd Even
// 8 Odd Even Odd Even Even Odd
// 9 Odd Even Even Odd Even Odd
//
// Note that the encoding for '0' uses the same parity as a UPC barcode. Hence
// a UPC barcode can be converted to an EAN-13 barcode by prepending a 0.
//
// The encoding is represented by the following array, which is a bit pattern
// using Odd = 0 and Even = 1. For example, 5 is represented by:
//
// Odd Even Even Odd Odd Even
// in binary:
// 0 1 1 0 0 1 == 0x19
//
static final int[] FIRST_DIGIT_ENCODINGS = {
0x00, 0x0B, 0x0D, 0xE, 0x13, 0x19, 0x1C, 0x15, 0x16, 0x1A
};
/**
* Start/end guard pattern.
*/
static final int[] START_END_PATTERN = {1, 1, 1,};
/**
* As above but also including the "even", or "G" patterns used to encode UPC/EAN digits.
*/
static final int[][] L_AND_G_PATTERNS;
/**
* "Odd", or "L" patterns used to encode UPC/EAN digits.
*/
static final int[][] L_PATTERNS = {
{3, 2, 1, 1}, // 0
{2, 2, 2, 1}, // 1
{2, 1, 2, 2}, // 2
{1, 4, 1, 1}, // 3
{1, 1, 3, 2}, // 4
{1, 2, 3, 1}, // 5
{1, 1, 1, 4}, // 6
{1, 3, 1, 2}, // 7
{1, 2, 1, 3}, // 8
{3, 1, 1, 2} // 9
};
/**
* Pattern marking the middle of a UPC/EAN pattern, separating the two halves.
*/
static final int[] MIDDLE_PATTERN = {1, 1, 1, 1, 1};
static {
L_AND_G_PATTERNS = new int[20][];
System.arraycopy(L_PATTERNS, 0, L_AND_G_PATTERNS, 0, 10);
for (int i = 10; i < 20; i++) {
int[] widths = L_PATTERNS[i - 10];
int[] reversedWidths = new int[widths.length];
for (int j = 0; j < widths.length; j++) {
reversedWidths[j] = widths[widths.length - j - 1];
}
L_AND_G_PATTERNS[i] = reversedWidths;
}
}
private static final int CODE_WIDTH = 3 + // start guard
(7 * 6) + // left bars
5 + // middle guard
(7 * 6) + // right bars
3; // end guard
private static final int DEFAULT_MARGIN = 10;
//This list should contain all positions of lines which should be longer than the other lines
private List<Integer> mLongLinePositions;
public CustomEAN13Writer() {
mLongLinePositions = new ArrayList<>();
}
/**
* #param target encode black/white pattern into this array
* #param pos position to start encoding at in {#code target}
* #param pattern lengths of black/white runs to encode
* #param startColor starting color - false for white, true for black
* #return the number of elements added to target.
*/
public int appendPatternAndConsiderLongLinePosition(boolean[] target, int pos, int[] pattern,
boolean startColor) {
boolean color = startColor;
int numAdded = 0;
for (int len : pattern) {
for (int j = 0; j < len; j++) {
//If the pattern is the start-, middle- or end-pattern save the position for rendering later
if (pattern.equals(START_END_PATTERN) || pattern.equals(MIDDLE_PATTERN) || pattern
.equals(START_END_PATTERN)) {
mLongLinePositions.add(pos);
}
target[pos++] = color;
}
numAdded += len;
color = !color; // flip color after each segment
}
return numAdded;
}
#Override
public boolean[] encode(final String contents) {
if (contents.length() != 13) {
throw new IllegalArgumentException(
"Requested contents should be 13 digits long, but got " + contents.length());
}
try {
if (!checkStandardUPCEANChecksum(contents)) {
throw new IllegalArgumentException("Contents do not pass checksum");
}
} catch (FormatException ignored) {
throw new IllegalArgumentException("Illegal contents");
}
int firstDigit = Integer.parseInt(contents.substring(0, 1));
int parities = FIRST_DIGIT_ENCODINGS[firstDigit];
boolean[] result = new boolean[CODE_WIDTH];
int pos = 0;
pos += appendPatternAndConsiderLongLinePosition(result, pos, START_END_PATTERN, true);
// See {#link #EAN13Reader} for a description of how the first digit & left bars are encoded
for (int i = 1; i <= 6; i++) {
int digit = Integer.parseInt(contents.substring(i, i + 1));
if ((parities >> (6 - i) & 1) == 1) {
digit += 10;
}
pos += appendPatternAndConsiderLongLinePosition(result, pos, L_AND_G_PATTERNS[digit],
false);
}
pos += appendPatternAndConsiderLongLinePosition(result, pos, MIDDLE_PATTERN, false);
for (int i = 7; i <= 12; i++) {
int digit = Integer.parseInt(contents.substring(i, i + 1));
pos += appendPatternAndConsiderLongLinePosition(result, pos, L_PATTERNS[digit], true);
}
appendPatternAndConsiderLongLinePosition(result, pos, START_END_PATTERN, true);
return result;
}
public BitMatrix encodeAndRender(String contents, int width, int height) {
boolean[] code = encode(contents);
int inputWidth = code.length;
// Add quiet zone on both sides.
int fullWidth = inputWidth + DEFAULT_MARGIN;
int outputWidth = Math.max(width, fullWidth);
int outputHeight = Math.max(1, height);
int multiple = outputWidth / fullWidth;
int leftPadding = (outputWidth - (inputWidth * multiple)) / 2;
BitMatrix output = new BitMatrix(outputWidth, outputHeight);
for (int inputX = 0, outputX = leftPadding; inputX < inputWidth;
inputX++, outputX += multiple) {
if (code[inputX]) {
int barcodeHeight = outputHeight;
//if the position isn't in the list for long lines we have to shorten the line by 5%
if (!mLongLinePositions.contains(inputX)) {
barcodeHeight = (int) ((float) outputHeight * 0.95f);
}
output.setRegion(outputX, 0, multiple, barcodeHeight);
}
}
return output;
}
/**
* Computes the UPC/EAN checksum on a string of digits, and reports whether the checksum is
* correct or not.
*
* #param s string of digits to check
* #return true iff string of digits passes the UPC/EAN checksum algorithm
* #throws FormatException if the string does not contain only digits
*/
static boolean checkStandardUPCEANChecksum(CharSequence s) throws FormatException {
int length = s.length();
if (length == 0) {
return false;
}
int sum = 0;
for (int i = length - 2; i >= 0; i -= 2) {
int digit = (int) s.charAt(i) - (int) '0';
if (digit < 0 || digit > 9) {
throw FormatException.getFormatInstance();
}
sum += digit;
}
sum *= 3;
for (int i = length - 1; i >= 0; i -= 2) {
int digit = (int) s.charAt(i) - (int) '0';
if (digit < 0 || digit > 9) {
throw FormatException.getFormatInstance();
}
sum += digit;
}
return sum % 10 == 0;
}
}
The second encode method returns an array of boolean that is a row of pixels. A true value is black, a false value is white. That array is extrapolated into your first image by: OneDimensionalCodeWriter::renderResult().
That method makes no provision for the human readable image. The separators are there in your first image, but they are not extended nor, obviously, is the human readable rendering of the number that is encoded.
My best advice is to fork the github repo and modify the renderResult method to do what you want. Obviously you need to provide something to your client, so I'd just do something quick in it's own branch. Ultimately the best thing is to do it correctly and offer the changes back to the zxing team.
I would assume that there should be a hint (EncodeHintType) added to allow a choice to make the barcode human readable. To save yourself time, I would post a message to their dev mailing list and see what they feel would be the best way to add this feature.
Related
This is the question:
You are given Q queries. Each query consists of a single number N . You can perform any of the operations on in each move:
If we take 2 integers a and b where N=a*b (a ,b cannot be equal to 1), then we can change N=max(a,b)
Decrease the value of N by 1 .
Determine the minimum number of moves required to reduce the value of to .
Input Format
The first line contains the integer Q.
The next Q lines each contain an integer,N .
Output Format
Output Q lines. Each line containing the minimum number of moves required > to reduce the value of N to 0.
I have written the following code. This code is giving some wrong answers and also giving time limit exceed error . Can you tell what are the the mistakes present in my code ? where or what I am doing wrong here?
My code:
public static int downToZero(int n) {
// Write your code here
int count1=0;
int prev_i=0;
int prev_j=0;
int next1=0;
int next2=Integer.MAX_VALUE;
if (n==0){
return 0;
}
while(n!=0){
if(n==1){
count1++;
break;
}
next1=n-1;
outerloop:
for (int i=1;i<=n;i++){
for (int j=1;j<=n;j++){
if (i*j==n){
if (prev_i ==j && prev_j==i){
break outerloop;
}
if (i !=j){
prev_i=i;
prev_j=j;
}
int max=Math.max(i,j);
if (max<next2){
next2=max;
}
}
}
}
n=Math.min(next1,next2);
count1++;
}
return count1;
}
This is part is coded for us:
public class Solution {
public static void main(String[] args) throws IOException {
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(System.getenv("OUTPUT_PATH")));
int q = Integer.parseInt(bufferedReader.readLine().trim());
for (int qItr = 0; qItr < q; qItr++) {
int n = Integer.parseInt(bufferedReader.readLine().trim());
int result = Result.downToZero(n);
bufferedWriter.write(String.valueOf(result));
bufferedWriter.newLine();
}
bufferedReader.close();
bufferedWriter.close();
}
}
Ex: it is not working for number 7176 ....
To explore all solution tree and find globally optimal solution, we must choose the best result both from all possible divisor pairs and from solution(n-1)
My weird translation to Java (ideone) uses bottom-up dynamic programming to make execution faster.
We calculate solutions for values i from 1 to n, they are written into table[i].
At first we set result into 1 + best result for previous value (table[i-1]).
Then we factor N into all pairs of divisors and check whether using already calculated result for larger divisor table[d] gives better result.
Finally we write result into the table.
Note that we can calculate table once and use it for all Q queries.
class Ideone
{
public static int makezeroDP(int n){
int[] table = new int[n+1];
table[1] = 1; table[2] = 2; table[3] = 3;
int res;
for (int i = 4; i <= n; i++) {
res = 1 + table[i-1];
int a = 2;
while (a * a <= i) {
if (i % a == 0)
res = Math.min(res, 1 + table[i / a]);
a += 1;
}
table[i] = res;
}
return table[n];
}
public static void main (String[] args) throws java.lang.Exception
{
int n = 145;//999999;
System.out.println(makezeroDP(n));
}
}
Old part
Simple implementation (sorry, in Python) gives answer 7 for 7176
def makezero(n):
if n <= 3:
return n
result = 1 + makezero(n - 1)
t = 2
while t * t <= n:
if n % t == 0:
result = min(result, 1 + makezero(n // t))
t += 1
return result
In Python it's needed to set recursion limit or change algorithm. Now use memoization, as I wrote in comments).
t = [-i for i in range(1000001)]
def makezeroMemo(n):
if t[n] > 0:
return t[n]
if t[n-1] < 0:
res = 1 + makezeroMemo(n-1)
else:
res = 1 + t[n-1]
a = 2
while a * a <= n:
if n % a == 0:
res = min(res, 1 + makezeroMemo(n // a))
a += 1
t[n] = res
return res
Bottom-up table dynamic programming. No recursion.
def makezeroDP(n):
table = [0,1,2,3] + [0]*(n-3)
for i in range(4, n+1):
res = 1 + table[i-1]
a = 2
while a * a <= i:
if i % a == 0:
res = min(res, 1 + table[i // a])
a += 1
table[i] = res
return table[n]
We can construct the directed acyclic graph quickly with a sieve and
then compute shortest paths. No trial division needed.
Time and space usage is Θ(N log N).
n_max = 1000000
successors = [[n - 1] for n in range(n_max + 1)]
for a in range(2, n_max + 1):
for b in range(a, n_max // a + 1):
successors[a * b].append(b)
table = [0]
for n in range(1, n_max + 1):
table.append(min(table[s] for s in successors[n]) + 1)
print(table[7176])
Results:
7
EDIT:
The algorithm uses Greedy approach and doesn't return optimal results, it just simplifies OP's approach. For 7176 given as example, below algorithm returns 10, I can see a shorter chain of 7176 -> 104 -> 52 -> 13 -> 12 -> 4 -> 2 -> 1 -> 0 with 8 steps, and expected answer is 7.
Let's review your problem in simple terms.
If we take 2 integers a and b where N=a*b (a ,b cannot be equal to 1), then we can change N=max(a,b)
and
Determine the minimum number of moves required to reduce the value of to .
You're looking for 2 factors of N, a and b and, if you want the minimum number of moves, this means that your maximum at each step should be minimum. We know for a fact that this minimum is reached when factors are closest to N. Let me give you an example:
36 = 1 * 36 = 2 * 18 = 3 * 12 = 4 * 9 = 6 * 6
We know that sqrt(36) = 6 and you can see that the minimum of 2 factors you can get at this step is max(6, 6) = 6. Sure, 36 is 6 squared, let me take a number without special properties, 96, with its square root rounded down to nearest integer 9.
96 = 2 * 48 = 3 * 32 = 4 * 24 = 6 * 16 = 8 * 12
You can see that your minimum value for max(a, b) is max(8, 12) = 12, which is, again, attained when factors are closest to square root.
Now let's look at the code:
for (int i=1;i<=n;i++){
for (int j=1;j<=n;j++){
if (i*j==n){
You can do this in one loop, knowing that n / i returns an integer, therefore you need to check if i * (n / i) == n. With the previous observation, we need to start at the square root, and go down, until we get to 1. If we got i and n / i as factors, we know that this pair is also the minimum you can get at this step. If no factors are found and you reach 1, which obviously is a factor of n, you have a prime number and you need to use the second instruction:
Decrease the value of N by 1 .
Note that if you go from sqrt(n) down to 1, looking for factors, if you find one, max(i, n / i) will be n / i.
Additionally, if n = 1, you take 1 step. If n = 2, you take 2 steps (2 -> 1). If n = 3, you take 3 steps (3 -> 2 -> 1). Therefore if n is 1, 2 or 3, you take n steps to go to 0. OK, less talking, more coding:
static int downToZero(int n) {
if (n == 1 || n == 2 || n == 3) return n;
int sqrt = (int) Math.sqrt(n);
for (int i = sqrt; i > 1; i--) {
if (n / i * i == n) {
return 1 + downToZero(n / i);
}
}
return 1 + downToZero(n - 1);
}
Notice that I'm stopping when i equals 2, I know that if I reach 1, it's a prime number and I need to go a step forward and look at n - 1.
However, I have tried to see the steps your algorithm and mine takes, so I've added a print statement each time n changes, and we both have the same succession: 7176, 92, 23, 22, 11, 10, 5, 4, 2, 1, which returns 10. Isn't that correct?
So, I found a solution which is working for all the test cases -
static final int LIMIT = 1_000_000;
static int[] solutions = buildSolutions();
public static int downToZero(int n) {
// Write your code here
return solutions[n];
}
static int[] buildSolutions() {
int[] solutions = new int[LIMIT + 1];
for (int i = 1; i < solutions.length; i++) {
solutions[i] = solutions[i - 1] + 1;
for (int j = 2; j * j <= i; j++) {
if (i % j == 0) {
solutions[i] = Math.min(solutions[i], solutions[i / j] + 1);
}
}
}
return solutions;
}
}
I am trying to add two binary numbers and then get their sum in binary system. I got their sum in decimal and now I am trying to turn it into binary. But there is problem that when I take their sum (in decimal) and divide by 2 and find remainders(in while loop), I need to put remainders into array in order print its reverse. However, there is an error in array part. Do you have any suggestions with my code? Thanks in advance.
Here is my code:
import java.util.Scanner;
public class ex1 {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int n = scan.nextInt();
int m = scan.nextInt();
int k = dec1(n)+dec2(m);
int i=0,c;
int[] arr= {};
while(k>0) {
c = k % 2;
k = k / 2;
arr[i++]=c; //The problem is here. It shows some //error
}
while (i >= 0) {
System.out.print(arr[i--]);
}
}
public static int dec1(int n) {
int a,i=0;
int dec1 = 0;
while(n>0) {
a=n%10;
n=n/10;
dec1= dec1 + (int) (a * Math.pow(2, i));
i++;
}
return dec1;
}
public static int dec2(int m) {
int b,j=0;
int dec2 = 0;
while(m>0) {
b=m%10;
m=m/10;
dec2= dec2 + (int) (b * Math.pow(2, j));
j++;
}
return dec2;
}
}
Here:
int[] arr= {};
creates an empty array. Arrays don't grow dynamically in Java. So any attempt to access any index of arr will result in an ArrayIndexOutOfBounds exception. Because empty arrays have no "index in bounds" at all.
So:
first ask the user for the count of numbers he wants to enter
then go like: int[] arr = new int[targetCountProvidedByUser];
The "more" real answer would be to use List<Integer> numbersFromUsers = new ArrayList<>(); as such Collection classes allow for dynamic adding/removing of elements. But for a Java newbie, you better learn how to deal with arrays first.
Why are you using two different methods to do the same conversion? All you need is one.
You could have done this in the main method.
int k = dec1(n)+dec1(m);
Instead of using Math.pow which returns a double and needs to be cast, another alternative is the following:
int dec = 0;
int mult = 1;
int bin = 10110110; // 128 + 48 + 6 = 182.
while (bin > 0) {
// get the right most bit
int bit = (bin % 10);
// validate
if (bit < 0 || bit > 1) {
throw new IllegalArgumentException("Not a binary number");
}
// Sum up each product, multiplied by a running power of 2.
// this is required since bits are taken from the right.
dec = dec + mult * bit;
bin /= 10;
mult *= 2; // next power of 2
}
System.out.println(dec); // prints 182
An alternative to that is to use a String to represent the binary number and take the bits from the left (high order position).
String bin1 = "10110110";
int dec1 = 0;
// Iterate over the characters, left to right (high to low)
for (char b : bin1.toCharArray()) {
// convert to a integer by subtracting off character '0'.
int bit = b - '0';
// validate
if (bit < 0 || bit > 1) {
throw new IllegalArgumentException("Not a binary number");
}
// going left to right, first multiply by 2 and then add the bit
// Each time thru, the sum will be multiplied by 2 which shifts everything left
// one bit.
dec1 = dec1 * 2 + bit;
}
System.out.println(dec1); // prints 182
One possible way to display the result in binary is to use a StringBuilder and simply insert the converted bits to characters.
public static String toBin(int dec) {
StringBuilder sb = new StringBuilder();
while (dec > 0) {
// by inserting at 0, the bits end up in
// correct order. Adding '0' to the low order
// bit of dec converts to a character.
sb.insert(0, (char) ((dec & 1) + '0'));
// shift right for next bit to convert.
dec >>= 1;
}
return sb.toString();
}
I need help writing a program that is given a specified number of coordinate points in the form (X,Y). The number of points that will be given is the first line in the program; it can be read in through a scanner.
I need to calculate the least amount of area to cover all of the points with the lines x = a, and y = b. So, the area would be a * b (Area of a rectangle).
However, one coordinate point (X, Y) must be removed to optimize the area. The point that is removed should minimize the area as much as possible. I need help writing algorithm to do so.
This is a sample input, and output that I was given ::
SAMPLE INPUT
4
2 4
1 1
5 2
17 25
SAMPLE OUTPUT
12
In this example, the first line of input (4) indicates that four points will be input. The next four lines are the coordinates in form (x, y). The last point which is (17, 25) is removed as the outlier which leaves us with the first three points.
If the three remaining points are graphed, they can all be inside a box (3 by 4) hence the output is 12; (3 * 4). It is OK for the line to be on the point like in this example. However, the outlier is not always the last point, or very big. The outlier could be very small, the area just needs to be minimized.
--
This is what I have so far (I know it's not very much..) - please help me!
It's mostly just the algorithm that I need help with..
import java.io.*;
import java.util.*;
public class Area {
public static void main(String args[]) {
Scanner scan = new Scanner(System.in);
int numOfPoints = scan.nextInt();
int Xcoordinates[] = new int[numOfPoints];
int Ycoordinates[] = new int[numOfPoints];
for (int i = 0; i <= numOfCows - 1; i++) {
Xcoordinates[i] = scan.nextInt();
Ycoordinates[i] = scan.nextInt();
}
Let you have 4 points (2 4), (1 1), (5 2), (17 25).
As you can always remove one point to optimize area hence,there are C(4,3) combinations possible of points,which are:
{ { (2 4), (1 1), (5 2) }, { (1 1), (5 2), (17 25) }, { (2 4), (5 2),(17 25) }, { (2 4),(1 1),(17 25) } }
Minimum area you can find for a set will be:
(Max(all x coordinates)-Min(all x coordinates)) * (Max(all y
coordinates)-Min(all y coordinates))
{ (2 4), (1 1), (5 2) }
Minimum area for this set is equal to (5-1)*(4-1) = 4*3 = 12
{ (1 1), (5 2), (17 25) }
Minimum area you can find for this set will be: (17-1)*(25-1) =
16*24 = 384
{ (2 4), (5 2), (17 25) }
Minimum area you can find for this set will be: (17-2)*(25-2) =
15*23 = 345
{ (2 4),(1 1),(17 25) }
Minimum area you can find for this set will be: (17-1)*(25-1) =
16*24 = 384
Out of all the area for the set { (2 4), (1 1), (5 2) } is minimum which is equal to 12 ,so the required answer is 12.
The bruteforce solution is of course to compute the area of every combination of points and select the minimum.
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int numOfPoints = scan.nextInt();
int[][] points = new int[numOfPoints][2];
for (int i = 0; i < numOfPoints; i++) {
points[i][0] = scan.nextInt();
points[i][1] = scan.nextInt();
}
// Testcase, comment everything above out.
/*
* int numOfPoints = 4; int[][] points = { { 2, 4 }, { 1, 1 }, { 5, 2 },
* { 17, 25 } };
*/
// As we try to minimize, we start with the biggest possible value.
int minArea = Integer.MAX_VALUE;
// We don't know which one to skip yet, so this value should be anything
// *but* a valid value.
int skippedPoint = -1;
// Pretty straightforward. Check every point, get minimum
for (int skipped = 0; skipped < numOfPoints; skipped++) {
int area = calculateArea(points, skipped);
if (area < minArea) {
skippedPoint = skipped;
minArea = area;
}
}
System.out.println("The original area was " + calculateArea(points, -1) + " units big.");
System.out.println("The minimized area is " + minArea + " units big.");
System.out.println("This was reached by leaving the " + (skippedPoint + 1) + ". point (" + Arrays.toString(points[skippedPoint]) + ") out.");
}
/**
* Implementation of Rajeev Singh's AABB-algorithm
*
* #param points
* All points
* #param skipped
* The point to skip
* #return The area of the axis-aligned bounding box of all points without
* the specified point
*/
private static int calculateArea(int[][] points, int skipped) {
// Initialize values with the opposite of the desired result, see
// minimization-problem above.
int max_x = Integer.MIN_VALUE, min_x = Integer.MAX_VALUE, max_y = Integer.MIN_VALUE, min_y = Integer.MAX_VALUE;
for (int i = 0; i < points.length; i++) {
if (i == skipped) {
continue; // This is where the magic happens. Continue
// immediatly jumps to the start of the loop.
}
int[] point_i = points[i];
if (point_i[0] > max_x) {
max_x = point_i[0];
}
if (point_i[0] < min_x) {
min_x = point_i[0];
}
if (point_i[1] > max_y) {
max_y = point_i[1];
}
if (point_i[1] < min_y) {
min_y = point_i[1];
}
}
return (max_x - min_x) * (max_y * min_y);
}
You now have the minimal area and the point that has been left out.
I am stuck on the coin denomination problem.
I am trying to find the lowest number of coins used to make up $5.70 (or 570 cents). For example, if the coin array is {100,5,2,5,1} (100 x 10c coins, 5 x 20c, 2 x 50c, 5 x $1, and 1 x $2 coin), then the result should be {0,1,1,3,1}
At the moment the coin array will consist of the same denominations ( $2, $1, 50c, 20c, 10c)
public static int[] makeChange(int change, int[] coins) {
// while you have coins of that denomination left and the total
// remaining amount exceeds that denomination, take a coin of that
// denomination (i.e add it to your result array, subtract it from the
// number of available coins, and update the total remainder). –
for(int i= 0; i< coins.length; i++){
while (coins[i] > 0) {
if (coins[i] > 0 & change - 200 >= 0) {
coins[4] = coins[4]--;
change = change - 200;
} else
if (coins[i] > 0 & change - 100 >= 0) {
coins[3] = coins[3]--;
change = change - 100;
} else
if (coins[i] > 0 & change - 50 >= 0) {
coins[2] = coins[2]--;
change = change - 50;
} else
if (coins[i] > 0 & change - 20 >= 0) {
coins[1] = coins[1]--;
change = change - 20;
} else
if (coins[i] > 0 & change - 10 >= 0) {
coins[0] = coins[0]--;
change = change - 10;
}
}
}
return coins;
}
I am stuck on how to deduct the values from coins array and return it.
EDIT: New code
The brute force solution is to try up to the available number of coins of the highest denomination (stopping when you run out or the amount would become negative) and for each of these recurse on solving the remaining amount with a shorter list that excludes that denomination, and pick the minimum of these. If the base case is 1c the problem can always be solved, and the base case is return n otherwise it is n/d0 (d0 representing the lowest denomination), but care must be taken to return a large value when not evenly divisible so the optimization can pick a different branch. Memoization is possible, and parameterized by the remaining amount and the next denomination to try. So the memo table size would be is O(n*d), where n is the starting amount and d is the number of denominations.
So the problem can be solved in pseudo-polynomial time.
The wikipedia link is sparse on details on how to decide if a greedy algorithm such as yours will work. A better reference is linked in this CS StackExchange question. Essentially, if the coin system is canonical, a greedy algorithm will provide an optimal solution. So, is [1, 2, 5, 10, 20] canonical? (using 10s of cents for units, so that the sequence starts in 1)
According to this article, a 5-coin system is non-canonical if and only if it satisfies exactly one of the following conditions:
[1, c2, c3] is non-canonical (false for [1, 2, 5])
it cannot be written as [1, 2, c3, c3+1, 2*c3] (true for [1, 2, 5, 10, 20])
the greedyAnswerSize((k+1) * c4) > k+1 with k*c4 < c5 < (k+1) * c4; in this case, this would require a k*10 < 20 < (k+1)*10; there is no integer k in that range, so this is false for [1, 2, 5, 10, 20].
Therefore, since the greedy algorithm will not provide optimal answers (and even if it did, I doubt that it would work with limited coins), you should try dynamic programming or some enlightened backtracking:
import java.util.HashSet;
import java.util.PriorityQueue;
public class Main {
public static class Answer implements Comparable<Answer> {
public static final int coins[] = {1, 2, 5, 10, 20};
private int availableCoins[] = new int[coins.length];
private int totalAvailable;
private int totalRemaining;
private int coinsUsed;
public Answer(int availableCoins[], int totalRemaining) {
for (int i=0; i<coins.length; i++) {
this.availableCoins[i] = availableCoins[i];
totalAvailable += coins[i] * availableCoins[i];
}
this.totalRemaining = totalRemaining;
}
public boolean hasCoin(int coinIndex) {
return availableCoins[coinIndex] > 0;
}
public boolean isPossibleBest(Answer oldBest) {
boolean r = totalRemaining >= 0
&& totalAvailable >= totalRemaining
&& (oldBest == null || oldBest.coinsUsed > coinsUsed);
return r;
}
public boolean isAnswer() {
return totalRemaining == 0;
}
public Answer useCoin(int coinIndex) {
Answer a = new Answer(availableCoins, totalRemaining - coins[coinIndex]);
a.availableCoins[coinIndex]--;
a.totalAvailable = totalAvailable - coins[coinIndex];
a.coinsUsed = coinsUsed+1;
return a;
}
public int getCoinsUsed() {
return coinsUsed;
}
#Override
public String toString() {
StringBuilder sb = new StringBuilder("{");
for (int c : availableCoins) sb.append(c + ",");
sb.setCharAt(sb.length()-1, '}');
return sb.toString();
}
// try to be greedy first
#Override
public int compareTo(Answer a) {
int r = totalRemaining - a.totalRemaining;
return (r==0) ? coinsUsed - a.coinsUsed : r;
}
}
// returns an minimal set of coins to solve
public static int makeChange(int change, int[] availableCoins) {
PriorityQueue<Answer> queue = new PriorityQueue<Answer>();
queue.add(new Answer(availableCoins, change));
HashSet<String> known = new HashSet<String>();
Answer best = null;
int expansions = 0;
while ( ! queue.isEmpty()) {
Answer current = queue.remove();
expansions ++;
String s = current.toString();
if (current.isPossibleBest(best) && ! known.contains(s)) {
known.add(s);
if (current.isAnswer()) {
best = current;
} else {
for (int i=0; i<Answer.coins.length; i++) {
if (current.hasCoin(i)) {
queue.add(current.useCoin(i));
}
}
}
}
}
// debug
System.out.println("After " + expansions + " expansions");
return (best != null) ? best.getCoinsUsed() : -1;
}
public static void main(String[] args) {
for (int i=0; i<100; i++) {
System.out.println("Solving for " + i + ":"
+ makeChange(i, new int[]{100,5,2,5,1}));
}
}
}
You are in wrong direction. This program will not give you an optimal solution. To get optimal solution go with dynamic algorithms implemented and discussed here. Please visit these few links:
link 1
link 2
link 3
This might be a beginner Java question but I would like to be able to calculate the number bytes it will require to store a whole number. And to convert that number into a byte array. Its do with some TLV encoding that I am performing. I realise that Java stores everything in twos completement but I am ignoring that, I am just interested in keeping the binary representation.
For example, if you had the number 256 it would take 2 bytes (as 1 byte can store 2^8-1, i think) then I would like to convert that number into a byte array.
Where:
byte[0] = 1111 1111
byte[1] = 0000 0001
Thanks for any help.
You can use Math.ceil(Math.log(number) / Math.log(2)) to get number of bits to store your number in binary format. Devide by 8 and you will get bytes to store your number.
The binary logarithm (log2) of a number gives you the number of bits needed to display the number. From there it should be easy to get to bytes.
Since Java only contains log10, you have to first convert it to log2. Consider the definition of change of base
We can then write Math.ceil(Math.log(256) / Math.log(2)) for the suggested answers... For instance, you would need 9 bits to save 256 or 2 bytes:
System.out.println(Integer.toBinaryString(256));
int numberBits = (int) Math.ceil(Math.log(256) / Math.log(2)) + 1;
int numberBytes = (int) (Math.ceil(Math.log(256) / Math.log(2)) / 8) + 1;
System.out.println(numberBits);
System.out.println(numberBytes);
100000000
9
2
I was just intrigued in how to get the byte[] of your requirement (to have them in revert order)... I started the implementation of the following test class with a char[]. Then, it came to my mind you could also a BitSet if you need operations over the bit set.
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.BitSet;
import java.util.List;
public class TestRevertBitSet {
public static class RevertableBitSet {
private BitSet bitSet;
private boolean flipped;
private RevertableBitSet(BitSet bitSet) {
this.bitSet = bitSet;
}
public static RevertableBitSet makeNew(char[] bitArray) {
BitSet byteValue = new BitSet(bitArray.length);
for (int i = 0; i < bitArray.length; i++) {
if (bitArray[i] == '1') {
byteValue.flip(i);
}
}
RevertableBitSet r = new RevertableBitSet(byteValue);
if (r.hasZeroCardinality()) {
r.flipAllBitsTrue();
} else {
r.revertBitsOrder();
}
return r;
}
public boolean hasAllBitsFlip() {
return this.flipped;
}
/**
* #return if all the bits are set.
*/
public boolean hasZeroCardinality() {
return this.bitSet.cardinality() == 0;
}
/**
* Flips all bits from the given bitSet to true.
*/
public void flipAllBitsTrue() {
this.bitSet.set(0, this.bitSet.size());
this.flipped = true;
}
/**
* Reverts the bits sequence. For instance, from 01100 to 00110.
*/
public void revertBitsOrder() {
for (int i = 0; i < 4; i++) {
boolean nthBit = this.bitSet.get(i);
this.bitSet.set(i, this.bitSet.get(7 - i));
this.bitSet.set(7 - i, nthBit);
}
}
/**
* #return a char array with values based on the bit indexes of the
* given bit set.
*/
public char[] toCharArray() {
char[] bitChars = new char[8];
for (int i = 0; i < bitChars.length; i++) {
bitChars[i] = bitSet.get(i) ? '1' : '0';
}
return bitChars;
}
/**
* #param bitIndex
* #return the boolean value of the given bit index.
*/
public boolean getBitBooleanAtIndex(int bitIndex) {
if (bitIndex > 7) {
return false;
}
return this.bitSet.get(bitIndex);
}
/**
* #param byteSetsList
* is the list of BitSet.
* #return the integer representation of the entire bit set.
*/
public static int convertSetToInteger(
List<RevertableBitSet> byteSetsList) {
int sum = 0;
int index = 0;
for (RevertableBitSet bitSet : byteSetsList) {
if (bitSet.hasAllBitsFlip()) {
for (int i = 0; i < 8; i++) {
index++;
}
continue;
}
for (int i = 7; i >= 0; i--) {
int bit = bitSet.getBitBooleanAtIndex(i) ? 1 : 0;
int intValue = (int) Math.pow((double) 2, (double) index++)
* bit;
sum = sum + intValue;
}
}
return sum;
}
#Override
public String toString() {
StringBuilder b = new StringBuilder();
b.append("[ ");
for (int i = 0; i < 7; i++) {
b.append(i);
b.append(" , ");
}
b.delete(0, b.length() - 2);
b.append(" ]");
return b.toString();
}
}
public static void main(String[] args) throws IOException {
int decimalNumber = 256;
System.out.println("Decimal Number: " + decimalNumber);
System.out.println(Integer.toBinaryString(decimalNumber));
int numberBits = (int) Math.ceil(Math.log(decimalNumber) / Math.log(2)) + 1;
int numberBytes = (int) (Math.ceil(Math.log(decimalNumber)
/ Math.log(2)) / 8) + 1;
System.out.println("Number of bits: " + numberBits);
System.out.println("Number of bytes: " + numberBytes);
List<RevertableBitSet> bytesSet = new ArrayList<RevertableBitSet>();
int bitsCounter = -1;
char[] binaryChars = Integer.toBinaryString(decimalNumber)
.toCharArray();
char[] currentChars = new char[8];
Arrays.fill(currentChars, '0');
for (int i = binaryChars.length - 1; i >= 0; i--) {
if (bitsCounter + 1 <= 7) {
currentChars[++bitsCounter] = binaryChars[i];
} else {
RevertableBitSet bitSet = RevertableBitSet
.makeNew(currentChars);
bytesSet.add(bitSet);
bitsCounter = -1;
Arrays.fill(currentChars, '0');
currentChars[++bitsCounter] = binaryChars[i];
}
}
bytesSet.add(RevertableBitSet.makeNew(currentChars));
System.out.println("------------");
for (RevertableBitSet bitSet : bytesSet) {
System.out.println(Arrays.toString(bitSet.toCharArray()));
}
System.out.println("------------");
System.out.println("Number: "
+ RevertableBitSet.convertSetToInteger(bytesSet));
}
}
The output of the execution of the main method is:
Decimal Number: 256
100000000
Number of bits: 9
Number of bytes: 2
------------
[1, 1, 1, 1, 1, 1, 1, 1]
[0, 0, 0, 0, 0, 0, 0, 1]
------------
Number: 256
Larger numbers as well work...
Decimal Number: 33456176
1111111101000000000110000
Number of bits: 26
Number of bytes: 4
------------
[0, 0, 1, 1, 0, 0, 0, 0]
[1, 0, 0, 0, 0, 0, 0, 0]
[1, 1, 1, 1, 1, 1, 1, 0]
[0, 0, 0, 0, 0, 0, 0, 1]
------------
Number: 33456176