Changing output into 4x4 matrices - java

So I'm working on a method in Java that basically takes a random string of letters then goes through the method and changes the string into parity bits, which is basically converting each character to its numeric value in binary.
This is what I have:
public class ShiftData {
//this is the method that where Logic is implemented..
static String shiftRows(String text) {
//character array to store given String elements into an array..
char[] chs = text.toCharArray();
StringBuffer samBuffer = new StringBuffer();
//loop through the length of the character array..
for (int i = 0; i < chs.length; i++) {
//adding characters to the StringBuffer...
samBuffer.append(Integer.toHexString((int) chs[i]));
// here in the above statement toHexString method pads parity bit and converts to hexadecimal value..
}
return samBuffer.toString();//returning the value
}
}
This is the code that converts the string into 4x4 matrices:
if(text !=null && !text.isEmpty()) {
int len = text.length();
int rem = len %16;
int padChars = 16-rem;
for(int i =0; i < (len+padChars); i++) {
if(i < len) {
System.out.print(text.charAt(i)+ " ");
} else {
System.out.print( "A ");
}
if((i+1) % 4 == 0)
System.out.println();
if((i+1) % 16 == 0)
System.out.println("\n");
}
}
So basically if the input string is: WVOGJTXQHUHXICWYYMGHTRKQHQPWKYVGLPYSPWGOINTOFOPMO
The output should look like this:
d7 56 cf 47
d4 d8 d1 ca
48 d8 48 55
59 c9 c3 d7
59 4d 47 48
d2 4b d1 d4
50 d7 48 d1
47 4b 59 56
cc 50 59 53
d7 47 cf 50
d4 cf c9 4e
4d c6 cf 50
cf 41 41 41
41 41 41 41
41 41 41 41
41 41 41 41
I just need help combining the codes! I can get them working separately but I cant get the output I need. Please show how you would code this.

Don't use StringBuffer. Use StringBuilder instead.
Your printing loop is writing one letter at a time, separated by 3 spaces (and newlines). Letters in hex consist of two hex digits, as you already show in the desired output, so that won't work.
Your code prints blank lines at the end, which you probably don't want.
Integer.toHexString() will return a single digits if value is 0-15.
static String shiftRows(String text) {
char[] chs = text.toCharArray();
StringBuilder samBuffer = new StringBuilder();
for (int i = 0; i < chs.length; i++)
samBuffer.append(String.format("%02x", (int)chs[i])); // always 2 hex digits, even for 0-15
return samBuffer.toString();
}
public static void main(String[] args) {
String text = shiftRows("WVOGJTXQHUHXICWYYMGHTRKQHQPWKYVGLPYSPWGOINTOFOPMO");
if (text != null && ! text.isEmpty()) {
int len = (text.length() + 31) / 32 * 32; // round up to next increment of 32 (16 hex pairs)
for (int i = 0; i < len; i += 2) {
if (i != 0 && i % 8 == 0) { // every 4 hex pairs, but not first time
System.out.println();
if (i % 32 == 0) // every 16 hex pairs
System.out.println();
}
if (i < text.length())
System.out.print(text.substring(i, i + 2) + " ");
else
System.out.print("41 ");
}
}
}

Related

How can I print the prime numbers ending with 1 in a given range and the nearest one after b?

Sample input :
10
100
Sample output :
11,31,41,61,71,101
from the above code I can get the sample output value upto the value 71,how can I get nearest prime number ending with 1 after b.
Here is the code I tried:
import java.util.*;
public class Program{
public static void main(String[] args){
Scanner in=new Scanner(System.in);
int a=in.nextInt();
int b=in.nextInt();
int i,j,count;
for(i=a;i<=b;i++)
{
for(j=2;j<=b;j++)
{
if(i%j==0)
break;
}
if(j==i && j%10==1)
{
System.out.println(i);
}
}
}
You do not need to divide a number by numbers up to it in order to check if it is prime. You just need to check up to its square root. Check https://en.wikipedia.org/wiki/Primality_test. Do it as follows:
Using a for loop
import java.util.Scanner;
public class Program {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
System.out.print("Enter two integers separated by space: ");
int a = in.nextInt();
int b = in.nextInt();
int i, j, sqrt;
// Note that there are three sections in the declaration of a 'for' loop:
// for(initialization;condition;change) where none of the sections is
// mandatory. There is no condition put in the loop syntax given below. The
// condition for termination has been put after printing the prime number.
for (i = a;; i++) {
sqrt = (int) Math.sqrt(i);
for (j = 2; j <= sqrt; j++) {
if (i % j == 0) {
break;
}
}
// If the loop with j completed without a break, the number is prime. Note that
// 1 is not a prime number.Also, the last digit of the number should be 1.
if (j > sqrt && Math.abs(i) != 1 && i % 10 == 1) {
System.out.print(i + " "); // Print the prime
if (i >= b) {// Condition for termination
break;
}
}
}
}
}
Alternatively, using a while loop
import java.util.Scanner;
public class Program {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
System.out.print("Enter two integers separated by space: ");
int a = in.nextInt();
int b = in.nextInt();
int i = a, j, sqrt;
while (true) {
sqrt = (int) Math.sqrt(i);
for (j = 2; j <= sqrt; j++) {
if (i % j == 0) {
break;
}
}
// If the loop with j completed without a break, the number is prime. Note that
// 1 is not a prime number.Also, the last digit of the number should be 1.
if (j > sqrt && Math.abs(i) != 1 && i % 10 == 1) {
System.out.print(i + " "); // Print the prime
if (i >= b) {// Condition for termination
break;
}
}
i++;
}
}
}
A sample run:
Enter two integers separated by space: 10 100
11 31 41 61 71 101
Another sample run:
Enter two integers separated by space: 10 200
11 31 41 61 71 101 131 151 181 191 211
Add condition in both the for loops like I<= b*2;
After that before printing the series add one more if block or add the condition in if(j==1 && j%10==1)
Condition-
You should have to check what is value of i and whether it's greater than b or not. If it's greater than b then it should be end with 1 and nearer value otherwise no need to print and break it as other values you don't need at all.
I'm assuming you need a prime satisfying these conditions:
within a range (lower to upper)
ending in 1
nearest to a query value
If so, wouldn't the best strategy be to search outwards in both directions (below and above) and stop when you first hit a prime ending in 1?
public static int nearest1Prime(final int lower, final int upper, final int val)
{
if(val < lower || val > upper) return 0;
int before, after;
if((val % 10) == 1)
{
if(isPrime(val))
return val;
before = val - 10;
after = val + 10;
}
else
{
int base = 10 * (val / 10);
if(val == base)
{
after = base+1;
before = after-10;
}
else
{
before = base+1;
after = before+10;
}
}
int prime = 0;
while(prime == 0 && (before >= lower || after <= upper))
{
if(before >= lower && isPrime(before))
prime = before;
if(after <= upper && isPrime(after) && (prime == 0 || (after-val) < (val-before)))
prime = after;
before -= 10;
after -= 10;
}
return prime;
}
public static boolean isPrime(int v)
{
for(int i=(int)Math.sqrt(v); i>1; i--)
{
if((v % i) == 0) return false;
}
return true;
}
Testing:
int lower = 10;
int upper = 100;
for(int i=lower; i<=upper; i++)
{
int prime = nearest1Prime(lower, upper, i);
System.out.println("Nearest Prime: " + i + " : " + prime);
}
Output:
10 : 11
11 : 11
12 : 11
13 : 11
14 : 11
15 : 11
16 : 11
17 : 11
18 : 11
19 : 11
20 : 11
21 : 11
22 : 31
23 : 31
24 : 31
25 : 31
26 : 31
27 : 31
28 : 31
29 : 31
30 : 31
31 : 31
32 : 31
33 : 31
34 : 31
35 : 31
36 : 31
37 : 41
38 : 41
39 : 41
40 : 41
41 : 41
42 : 41
43 : 41
44 : 41
45 : 41
46 : 41
47 : 41
48 : 41
49 : 41
50 : 41
51 : 41
52 : 61
53 : 61
54 : 61
55 : 61
56 : 61
57 : 61
58 : 61
59 : 61
60 : 61
61 : 61
62 : 61
63 : 61
64 : 61
65 : 61
66 : 61
67 : 71
68 : 71
69 : 71
70 : 71
71 : 71
72 : 71
73 : 71
74 : 71
75 : 71
76 : 71
77 : 71
78 : 71
79 : 71
80 : 71
81 : 71
82 : 71
83 : 71
84 : 71
85 : 71
86 : 71
87 : 71
88 : 71
89 : 71
90 : 71
91 : 71
92 : 71
93 : 71
94 : 71
95 : 71
96 : 71
97 : 71
98 : 71
99 : 71
100 : 71
Here's how you can do it, run the first loop indefinitely and break it when i is greater than b and it's a prime with 1 at the end.
This is the implementation just modifying your code a bit-
import java.util.*;
class Program{
public static void main(String[] args){
Scanner in=new Scanner(System.in);
int a=in.nextInt();
int b=in.nextInt();
boolean flag = false;
int i,j,count;
for(i=a;;i++) {
if(i>b) flag = true;
for(j=2;j<=i;j++) {
if(i%j==0)
break;
}
if(j==i && j%10==1) {
System.out.println(i);
if(flag) break;
}
}
}
}
Try this with a few improvements.
first check to see if divisible by 2
then, since 2 is taken care of, divide only by odd numbers
starting with 3, not exceeding the sqrt of the number under test.
then just continue until the search parameter are met.
Scanner in = new Scanner(System.in);
int a = in.nextInt();
int b = in.nextInt();
outer:
for (int i = a; i <= Integer.MAX_VALUE; i++) {
// first check division by 2 so you can increment by 2 later
if (i % 2 == 0) {
continue;
}
// increment from 3 to square root of i by 2's
for (int j = 3; j <= Math.sqrt(i); j+=2) {
if (i % j == 0) {
// not prime so continue with outer loop
continue outer;
}
}
if (i % 10 == 1) {
System.out.print(i + " ");
// keep searching until i > b.
if (i > b) {
break;
}
}
}
for input of 10 100 Prints
11 31 41 61 71 101

What are the bytes between the strings in Mifare NFC? [duplicate]

This question already has answers here:
Reading Mifare Classic returns strange characters
(2 answers)
Closed 4 years ago.
When I'm reading a Mifare classic 4k card from block to block and convert the bytes to hexadecimal and then to UTF8/ASCII I get weird characters that probably control bytes and not actual text.
Since I'm just converting the whole block directly to UTF, what should I instead do to utilize those bits in between?
Below are the readings I get and to the left the expected translated value.
If you convert the hex yourself you'll see there are strange characters between the words.
c5 42 4e 49 44 00 07 4f 4f 4f 4f 4f 4f 00 4b 42 "Ã…bnid" "OOOOOO" "KB"
44 44 44 20 44 44 44 44 44 00 82 4d 00 c9 31 39 "DDD DDDDD" "M" "19"
39 34 34 33 34 32 00 d0 4e 4f 39 36 36 36 35 31 "944342" "NO966651"
00000000000070f78800000000000000
30 32 32 20 20 41 53 00 d3 54 4f 54 41 4c 20 4b "022" "AS" "Total k"
4f 4e 54 52 4f 4f 4f 20 41 53 20 00 c9 30 32 38 "ONTROOO AS" "028"
37 30 34 33 33 00 c9 32 30 32 31 30 32 31 31 00 "70433" "20210211"
00000000000070f78800000000000000
How can I implement a method that takes in either a string of hex or array of bytes[] and only returns the words by comma seperation?
You can read by address, probably, you only require to read by data address.
Data Address start from 0 to 63 for Mifare Classic card, 16 sectors with 4 blocks (=1024 bytes)). But Address 0 always store UID or Manufacturer ID. So, start reading from Address 1, Address 2...Address 63. Let me break down for you,
Sector 0: Address 0 , Address 1, Address 2, Address 3
UID/ManufacturerID, Data , Data ,Sector Trail (KeyA,AccessKey,KeyB)
Sector 1: Address 4, Address 5, Address 6, Address 7
Data , Data , Data , Sector Trail
...
Sector 63 ...
So Sector Trail = 00000000000070f78800000000000000
KeyA = 000000000000
AccessKey = 70f78800
KeyB = 000000000000
So every sector, you skip the last address if you don't set read and write protection.So Try this.And Change accordingly, this could be sufficient to read
// final data
String data="";
// read sector 1 and 2
for(int sector = 1; sector < 3, sector++){
// auth sector
auth = mfc.authenticateSectorWithKeyA(sector, bytekey3);
if(auth) {
// read blocks from sector
data += convertHexToString(readBlockData(sector)).trim();
}
}
// read block
private String readBlockData(int sector) {
String blockvalues = "";
// Read all blocks in sector
for (int block = 0; (block < mfc.getBlockCountInSector(sector)); ++block) {
// Get block number for sector + block
int blockIndex = (mfc.sectorToBlock(sector) + block);
try {
// Create a string of bits from block data and fix endianness
// http://en.wikipedia.org/wiki/Endianness
if (block < 3) {
// Read block data from block index
byte[] data = mfc.readBlock(blockIndex);
if (!(sector == 0 && block == 0)) {
String temp = ByteArrayToHexString(data);
blockvalues += temp;
Log.i(TAG, "Block " + blockIndex + " : " + temp);
rawData += ("Block " + blockIndex + " : " + temp + "\n");
}
}
} catch (IOException e) {
Log.e(TAG, "Exception occurred " + e.getLocalizedMessage());
}
}
return blockvalues.trim();
}
public String convertHexToString(String hex) {
StringBuilder sb = new StringBuilder();
StringBuilder temp = new StringBuilder();
//49204c6f7665204a617661 split into two characters 49, 20, 4c...
for (int i = 0; i < hex.length() - 1; i += 2) {
//grab the hex in pairs
String output = hex.substring(i, (i + 2));
//convert hex to decimal
int decimal = Integer.parseInt(output, 16);
//convert the decimal to character
sb.append((char) decimal);
temp.append(decimal);
}
System.out.println("Decimal : " + temp.toString());
return sb.toString().trim();
}
private String ByteArrayToHexString(byte[] inarray) {
int i, j, in;
String[] hex = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A",
"B", "C", "D", "E", "F"};
String out = "";
for (j = 0; j < inarray.length; ++j) {
in = inarray[j] & 0xff;
i = (in >> 4) & 0x0f;
out += hex[i];
i = in & 0x0f;
out += hex[i];
}
return out;
}
last part will be string manipulation. so basically, replay all the double quote with space and use String[]yourdata = data.split("\s+"); and you will get your data. Some of the code I borrow from this link

How to drop min and max for each line. Java

public class Average {
static Integer[][] myDouble = new Integer[10][12];
static int x = 0, y = 0;
static int strDouble;
public Average() {
try {
BufferedReader in = new BufferedReader(new FileReader("StudentIdAverage.txt"));
String line;
while ((line = in.readLine()) != null) {
String[] values = line.split("\\s+");
for (String str : values) {
strDouble = Integer.parseInt(str);
myDouble[x][y] = strDouble;
y = y + 1;
}
x = x + 1;
y = 0;
}
in.close();
} catch (IOException ioException) {
}
}
public static void main(String[] args) {
Average arr = new Average();
for (int i = 0; i < myDouble.length; ++i) {
IntSummaryStatistics statistics = Arrays.asList(myDouble[i]).stream().filter(intValue -> intValue != null).collect(Collectors.summarizingInt(Integer::intValue));
System.out.println("Average: " + statistics.getAverage() + ", min: " + statistics.getMin() + ", max: " + statistics.getMax());
}
for (int k = 0; k < myDouble.length; ++k) {
int count = 0; // count the values used to calculate sum
double sum = 0;
double average = 0;
for (int j = 0; j < myDouble[k].length; ++j) {
if (myDouble[k][j] == null) //skip the null values
{
continue;
}
//Arrays.sort(myDouble[i]);
sum += myDouble[k][j];
count++;
System.out.print(Average.myDouble[k][j] + " ");
}
average = (sum / count); //use count instead of lenght
System.out.println(" ");
System.out.println(average);
}
}
}
input txt file
45 72 90 50 67 63 81 71 55 56 80 74/n 55 54 79 72 75 68/n 51 88 79 72/n 98 52 52 53 50 92 67 99 92 50 61 91/n 94 48 53 92 97/n 97 69 77 74 68 54 87 74 54 83 58 69/n 75 49 87 61 66 53 79 48 96 60/n 58 71 51 73 53 75 93 81 45 69 78 65/n 50 88 78 81 99 61 97 70 87 80 69/n 91 89 97 80 93 82 92 49 52 69 96 61
Given an array, myDouble[k] of size myDouble[k].length (call it L), dropping the min and max really means ignore the min and max. Since the sum is calculated as average/size, ignore the min and max values.
The sum is in the form newsum + min + max. Obtain the new sum by subtracting min and max from sum: sum -= (min + max).
You can get the min and max manually so you really are using just one for loop. Start min and max at the first non-null entry, and update min and max if the next entry is strictly less or strictly greater than the (candidate) current value, respectively.
The new size will also decrease by two (Beware if size is two or less!). That means, the average excluding min and max is the new sum/(myDouble[k].length - 2).
Simply keep track of the min and max value then substract both value at the end. You don't need to change the rest. This will allow you to get the average value without the need to read the line twice (to remove those values).
double min = Double.MAX_VALUE;
double max = Double.MIN_VALUE;
for (int j = 0; j < myDouble[k].length; ++j) {
if (myDouble[k][j] == null) // skip the null values
{
continue;
}
min = Math.min(myDouble[k][j], min);
max = Math.max(myDouble[k][j], max);
...
}
sum = sum - min - max;
If you can find those value twice, you will need to use a way to count the occurrence of those value. But you get the idea here.
Note that another solution would be to sort the array then skip the first and last value :
double[] sortedArray = Arrays.sort(myDouble[k]);
for (int j = 1; j < sortedArray.length - 1; ++j) {
sum += sortedArray[j];
}
This solution is easier but required more memory, for big list I would not recommend it (but performance is not an issue)

Two dimensional array with different row length. I need to drop min, max and calculate the average for each line in Java

public class Average {
static int[][] myDouble = new int[10][12];
static int x = 0, y = 0;
static int strDouble;
public Average() {
try {
BufferedReader in = new BufferedReader(new FileReader("StudentIdAverage.txt"));
String line;
while ((line = in.readLine()) != null) {
String[] values = line.split("\\s+");
for (String str : values) {
strDouble = Integer.parseInt(str);
myDouble[x][y] = strDouble;
y = y + 1;
}
x = x + 1;
y = 0;
}
in.close();
} catch (IOException ioException) {
}
}
public static void main(String[] args) {
Average arr = new Average();
//int[][] residuescores = arr.myDouble;
for (int i = 0; i < myDouble.length; ++i) {
int sum = 0;
int average = 0;
for (int j = 0; j < myDouble[i].length; ++j) {
Arrays.sort(myDouble[i]);
sum+=myDouble[i][j];
System.out.print(Average.myDouble[i][j] + " ");
}
average = (sum/myDouble[i].length);
System.out.println(" ");
System.out.println(average);
}
}
}
input File:-
45 72 90 50 67 63 81 71 55 56 80 74/n 55 54 79 72 75 68/n 51 88 79
72/n 98 52 52 53 50 92 67 99 92 50 61 91/n 94 48 53 92 97/n 97 69 77
74 68 54 87 74 54 83 58 69/n 75 49 87 61 66 53 79 48 96 60/n 58 71 51
73 53 75 93 81 45 69 78 65/n 50 88 78 81 99 61 97 70 87 80 69/n 91 89
97 80 93 82 92 49 52 69 96 61
If you are using java 8 you can utilize streams and SummaryStatistics to calculate average/min/max like below
static Integer[][] myDouble = new Integer[10][12];
for (int i = 0; i < myDouble.length; ++i) {
IntSummaryStatistics statistics = Arrays.asList(myDouble[i]).stream().filter(intValue -> intValue!=null).collect(Collectors.summarizingInt(Integer::intValue));
System.out.println("Average: "+statistics.getAverage()+", min: "+statistics.getMin()+", max: "+statistics.getMax());
}
If you can not use java 8 then note that the issue with your code is that you are using primitive int in your array which will initialize the values to 0 and thus you get 0 when the row has less values than 12. One way to solve it is to change your array to Integer class but remember to skip the entries which have null as now instead of 0 you will get null in the rows with less entries.
your code working with int array changed to Integer, skipping nulls and using count instead of array.length:
for (int i = 0; i < myDouble.length; ++i) {
int count = 0; // count the values used to calculate sum
int sum = 0;
int average = 0;
for (int j = 0; j < myDouble[i].length; ++j) {
if(myDouble[i][j] == null) //skip the null values
continue;
//Arrays.sort(myDouble[i]);
sum+=myDouble[i][j];
count++;
System.out.print(App.myDouble[i][j] + " ");
}
average = (sum/count); //use count instead of lenght
System.out.println(" ");
System.out.println(average);
}

Display 0 value in hex file

I am working on a hex file and display its content but if the value had "0". It did not appear when i print it out.
for example
0 0 0 b7 7a 7a e5 db 40 2 0 c0 0 0 9 18 16 0 e3 1 40 0 0 3f 20 f0 1 5 0 0 0 0 0 0 41 bc 7a e5 db 40 2 0 c0 1 0 9 18 16 0 e3 1 40 0 0 3f 20 f0 1 5 0 0 0 0 0 0 53 3f 7b e5 db 40 2 0 c0 3 0 9 2 19 24 3d 0 22 68 1 db 9
Code
String filename = "C:\\tm09888.123";
FileInputStream in = null;
int readHexFile = 0;
char hexToChar = ' ';
String[] bytes = new String[10];
try
{
in = new FileInputStream(filename);
while((readHexFile = in.read()) != -1)
{
if (Integer.toHexString(readHexFile).equals("f0"))
{
System.out.print("\n\n\n");
}
System.out.print(Integer.toHexString(readHexFile) + " ");
}
}
catch (IOException ex)
{
Logger.getLogger(NARSSTest.class.getName()).log(Level.SEVERE, null, ex);
}
}
When I printed out the file the "0"s did not appear and values such as "c0" became "c".
How I do i rewrite the code to display the "0"s?
Integer.toHexString doesn't guarantee returning a two-digit result.
If you want it to always be two digits, you could use String.format instead:
System.out.print(String.format("%02x ", readHexFile));
When display it on the screen "0" values did not appear and value like "c0" become only "c"
I suspect it's more likely that "0c" becomes just "c". I'd expect "c0" to be fine.
The problem is that you're using Integer.toHexString which will only use as many digits as it needs to. You could manually fix this by writing:
if (readHexFile < 0x10) {
System.out.print("0");
}
Alternatively, just use:
private static final char[] HEX_DIGITS = "0123456789abcdef".toCharArray();
...
System.out.print(HEX_DIGITS[readHexFile >> 4]);
System.out.print(HEX_DIGITS[readHexFile % 15]);
System.out.print(" ");
Or even more simply:
System.out.printf("%02x ", readHexFile);
Also note that there's no need to convert to a hex string to compare with 0xf0. You can use:
if (readHexFile == 0xf0) {
System.out.print("\n\n\n");
}
I cannot say what the problem is with the code, but it seems things would be much clearer if you used Scanner
Scanner sc = new Scanner(new File(fileName));
while(sc.hasNext()) {
String s = sc.next();
System.out.println(s);
}

Categories