31 ianuarie 2024

Exemplu de lucru pe biți: privilegii in BD

Lista de privilegii = intrări într-un dicționar, cu valoarea = puteri ale lui 2.

1 Citire articole

2 Scriere articole

4 Aprobare membri noi

8 Dezactivare membri

16 Editare articole


Utilizatori/entități din BD: au asociată o mască = suma privilegiilor pe care le au.

1 user1 1 ...

2 user2 3 ...

3 user3 15 ...

4 user4 31 ...

User1: poate doar citi
User2: citire, scriere articole
User3: toate drepturile, mai puțin Editare articole
User4: toate drepturile

public static boolean isActionAllowed(int requiredPriv, int userMask) {
return (requiredPriv & userMask) > 0;
}

18 ianuarie 2024

50 DSA-Questions: #15, #16

#15. Longest Substring Without Repeating Characters
Given a string s, find the length of the longest substring without repeating characters.
public class Exercise15 {
private final String INPUT = "abcabcbb"; // abc
// private final String INPUT = "abcadbcbb"; // bcad
//private final String INPUT = "pwwkew"; // wke
// private final String INPUT = "georgiana"; // eorgian
// private final String INPUT = "georoi"; // geor
// private final String INPUT = "gerryinyr"; // ryin

private boolean containsChar(String content, char currentChar) {
return content.chars().filter(ch -> ch == currentChar).findFirst().isPresent();
}

private String replaceCharAtTheEnd(String content, char stripped) {
int index = content.indexOf(stripped);
return content.concat(String.valueOf(stripped)).substring(index + 1);
}

private void solve() {
assert(!INPUT.isEmpty());

String currentStrike = String.valueOf(INPUT.charAt(0));
String bestStrike = currentStrike;

for (int i=1; i<INPUT.length(); i++) {
final char currentChar = INPUT.charAt(i);
if (!containsChar(currentStrike, currentChar)) {
currentStrike = currentStrike.concat(String.valueOf(currentChar)); // continue current strike
} else {
if (currentStrike.length() > bestStrike.length()) {
bestStrike = currentStrike;
}
currentStrike = replaceCharAtTheEnd(currentStrike, currentChar); // reset strike
}
}

System.out.println(currentStrike.length() > bestStrike.length() ? currentStrike : bestStrike);
}


public static void main(String args[]) {
new Exercise15().solve();
}
}
#16. Longest Repeating Character Replacement
You are given a string s and an integer k. You can choose any character of the string and change it to any other uppercase English character. You can perform this operation at most k times. Return the length of the longest substring containing the same letter you can get after performing the above operations.
public class Exercise16 {
// private final String INPUT = "ABAB"; // B->A , B->A => AaAa, size of the longest repeating consecutive char = 4
// private final String INPUT = "ADFAAED"; // AaaAAEG, size = 5
// private final String INPUT = "PGAPTARGKLGZ"; // PppPTARGKLGZ, size = 4
// private final String INPUT = "GEO"; // Ggg, size = 3
// private final String INPUT = "ABCDEFGHA"; // AaaDEFGHA, size = 3
// private final int K = 2;

private final String INPUT = "ANAAREMERELE"; // ANAAREeEeEeE, size = 7
private final int K = 3;

private Map<Character, Occurrence> occurrenceMap() {
Map<Character, Occurrence> map = new HashMap<>();
for (int i=0; i<INPUT.length(); i++) {
char key = INPUT.charAt(i);
if (map.containsKey(key)) {
Occurrence occurrence = map.get(key);
occurrence.addIndex(i);
} else {
map.put(key, new Occurrence(i));
}
}
return map;
}

private List<Map.Entry<Character, Occurrence>> filterSortDesc(Map<Character, Occurrence> map) {
return map.entrySet().stream()
.filter(entry -> entry.getValue().getCount() > 1)
.sorted((e1, e2) -> e2.getValue().findMaxConsec() - e1.getValue().findMaxConsec())
.collect(Collectors.toList());
}

private int getDefaultProfit() {
return (K < INPUT.length() ? K+1 : INPUT.length());
}

private void solve() {
assert(!INPUT.isEmpty());

List<Map.Entry<Character, Occurrence>> sortedEntries = filterSortDesc(occurrenceMap());
if (sortedEntries.isEmpty()) {
System.out.println("Max = " + getDefaultProfit());
return;
}

System.out.println("Max = " + sortedEntries.get(0).getValue().getMaxConsec());
}

public static void main(String args[]) {
new Exercise16().solve();
}

private class Occurrence {
private List<Integer> indexes;
private int maxConsec;

public Occurrence(int index) {
this.indexes = new ArrayList<>();
this.addIndex(index);
}

public void addIndex(Integer index) {
this.indexes.add(index);
}

public int getCount() {
return indexes.size();
}

public int findMaxConsec() {
int credit = K;
int maxProfit = 0;
for (int i=0; i<indexes.size()-1; i++, credit = K) {
int profit = 0;
if (credit >= indexes.get(i+1) - indexes.get(i) - 1) { // can afford a strike
credit -= indexes.get(i+1) - indexes.get(i) - 1; // extract from K
profit = indexes.get(i+1) - indexes.get(i) - 1 + 2; // no. elements comprised

// INPUT[indexes.get(i)] == INPUT[indexes.get(i+1)]

for (int j=indexes.get(i+1) + 1; j<INPUT.length(); j++) { // go right
if (INPUT.charAt(j) == INPUT.charAt(indexes.get(i))) { // free one
profit++;
}
else {
if (credit > 0) { // buy one
profit++;
credit--;
} else {
break;
}
}
}

for (int j=indexes.get(i) - 1; j>=0; j--) { // go left
if (INPUT.charAt(j) == INPUT.charAt(indexes.get(i))) { // free one
profit++;
} else {
if (credit > 0) { // buy one
profit++;
credit--;
} else {
break;
}
}
}
}

if (profit > maxProfit) {
maxProfit = profit;
}
}

if (maxProfit == 0) {
maxProfit = getDefaultProfit();
}

this.maxConsec = maxProfit;
return maxProfit;
}

public int getMaxConsec() {
return maxConsec;
}
}
}

09 ianuarie 2024

50 DSA-Questions: #14

#14. Word Search
Given an m x n grid of characters board and a string word, return true if the word exists in the grid. The word can be constructed from letters of sequentially adjacent cells, where adjacent cells are horizontally or vertically neighboring. The same letter cell may not be used more than once.
public class Exercise14 {
private final String[][] BOARD = {{"A", "B", "C", "E"},{"S", "F", "C", "S"},{"A", "D", "E", "E"}}; // 1 <= m, n <= 6
// private final String WORD = "ABCCED"; // 1 <= length <= 15
// private final String WORD = "SEE";
private final String WORD = "ABCB";

private boolean isCellFit(int i, int j , int wordPos) {
if (i < 0 || i >= BOARD.length || j < 0 || j >= BOARD[0].length || wordPos >= WORD.length()) {
return false; // out of grid
}
if (BOARD[i][j].length() > 1) {
return false; // already been there
}
return BOARD[i][j].charAt(0) == WORD.charAt(wordPos);
}

private void resetBoard() {
for (int i=0; i<BOARD.length; i++) {
for (int j = 0; j < BOARD[0].length; j++) {
BOARD[i][j] = BOARD[i][j].charAt(0) + "";
}
}
}

private boolean searchWordDFS(int i, int j, int wordPos) {
if (isCellFit(i, j, wordPos)) {
if (wordPos == WORD.length() - 1) {
return true;
}
BOARD[i][j] += BOARD[i][j]; // mark as visited
boolean found = searchWordDFS(i, j + 1, wordPos + 1);
if (!found) {
found = searchWordDFS(i, j - 1, wordPos + 1);
}
if (!found) {
found = searchWordDFS(i + 1, j, wordPos + 1);
}
if (!found) {
found = searchWordDFS(i - 1, j, wordPos + 1);
}
return found;
}
return false;
}

private void solve() {
for (int i=0; i<BOARD.length; i++) {
for (int j=0; j<BOARD[0].length; j++) {
resetBoard();
boolean found = searchWordDFS(i, j, 0);
if (found) {
System.out.println("True");
return;
}
}
}
System.out.println("False");
}


public static void main(String args[]) {
new Exercise14().solve();
}
}

02 ianuarie 2024

50 DSA-Questions: #12, #13

#12. Spiral Matrix
Given an m x n matrix, return all elements of the matrix in spiral order.
public class Exercise12 {
private final Integer[][] MATRIX = {{1,2,3},{4,5,6},{7,8,9}}; // [1,2,3,6,9,8,7,4,5]
// private final Integer[][] MATRIX = {{1,2,3,4},{5,6,7,8},{9,10,11,12}}; // [1,2,3,4,8,12,11,10,9,5,6,7]
// private final Integer[][] MATRIX = {{1,2,3,4, 5},{6,7,8,9,0},{9,8,7,6,5}, {4,3,2,1,0}, {9,1,2,3,4}};

private enum DIRECTION {LEFT_TO_RIGHT, TOP_TO_BOTTOM, RIGHT_TO_LEFT, BOTTOM_TO_TOP};

private void run(int i, int j, DIRECTION direction, int cycle) {
switch (direction) {
case LEFT_TO_RIGHT:
if (j >= MATRIX[0].length-cycle) {
return;
}
for (int jj=j; jj<MATRIX[0].length-cycle; jj++) {
System.out.print(MATRIX[i][jj] + " ");
}
System.out.println();
run(i+1,MATRIX[0].length - cycle - 1, DIRECTION.TOP_TO_BOTTOM, cycle);
break;
case TOP_TO_BOTTOM:
if (i >= MATRIX.length-cycle) {
return;
}
for (int ii=i; ii<MATRIX.length-cycle; ii++) {
System.out.print(MATRIX[ii][j] + " ");
}
System.out.println();
run(MATRIX.length - cycle - 1, j-1, DIRECTION.RIGHT_TO_LEFT, cycle);
break;
case RIGHT_TO_LEFT:
for (int jj=j; jj>=cycle; jj--) {
System.out.print(MATRIX[i][jj] + " ");
}
System.out.println();
run(i-1, cycle, DIRECTION.BOTTOM_TO_TOP, cycle);
break;
case BOTTOM_TO_TOP:
for (int ii=i; ii>cycle; ii--) {
System.out.print(MATRIX[ii][j] + " ");
}
System.out.println();
run(cycle + 1,j+1, DIRECTION.LEFT_TO_RIGHT, cycle + 1);
break;
}
}

private void solve() {
run(0, 0, DIRECTION.LEFT_TO_RIGHT, 0);
}

public static void main(String args[]) {
new Exercise12().solve();
}
}
#13. Rotate Image
You are given an n x n 2D matrix representing an image, rotate the image by 90 degrees (clockwise). You have to rotate the image in place, which means you have to modify the input 2D matrix directly. DO NOT allocate another 2D matrix and do the rotation.
public class Exercise13 {
private final int MARKER = 1000000; // marks that Mij has been updated
// private final int[][] MATRIX = {{1,2,3},{4,5,6},{7,8,9}}; // n x n, -1000 <= matrix[i][j] <= 1000
// private final Integer[][] MATRIX = {{1,2,3,4, 5},{6,7,8,9,0},{9,8,7,6,5}, {4,3,2,1,0}, {9,1,2,3,4}};
// private final Integer[][] MATRIX = {{1,2,-3,-4},{0,7,8,-9},{9,8,-7,6}, {4,0,2,-1}};
private final Integer[][] MATRIX = {{1000,2},{-1000,7}};
private int MAX_VALUE = 1001;

private int getCorrespondingElement90Cw(int i, int j) {
return MATRIX[MATRIX.length-1-j][i];
}

private int getCorrespondingElement90Ccw(int i, int j) {
return MATRIX[j][MATRIX.length-1-i];
}

private int getCorrespondingElement180(int i, int j) {
return MATRIX[MATRIX.length-1-i][MATRIX.length-1-j];
}

private void solveOnlyDisplay() {
for (int i=0; i<MATRIX.length; i++) {
for (int j = 0; j < MATRIX[0].length; j++) {
System.out.print(getCorrespondingElement90Cw(i,j) + " ");
}
System.out.println();
}
System.out.println();
}

private void addToOriginalMatrix(int valueToAdd) {
for (int i=0; i<MATRIX.length; i++) {
for (int j=0; j<MATRIX[0].length; j++) {
MATRIX[i][j] = MATRIX[i][j] + valueToAdd;
}
}
}

private int getMatrixMin() {
int minElem = MAX_VALUE;
for (int i=0; i<MATRIX.length; i++) {
for (int j=0; j<MATRIX[0].length; j++) {
if (MATRIX[i][j] < minElem) {
minElem = MATRIX[i][j];
}
}
}
return minElem;
}

private void display() {
for (int i=0; i<MATRIX.length; i++) {
for (int j = 0; j < MATRIX[0].length; j++) {
System.out.print(MATRIX[i][j] + " ");
}
System.out.println();
}
System.out.println();
}

private void solveWithSaving() {
assert(MATRIX.length == MATRIX[0].length);
int minValue = getMatrixMin();
if (minValue < 0) {
addToOriginalMatrix(- minValue); // make all values positive
MAX_VALUE -= minValue; // update max possible
}

// in place saving 90 degrees clockwise matrix rotation

// extra loading matrix: Mij = MARKER + Mij * MAX_VALUE + Mij_rotated
for (int i=0; i<MATRIX.length; i++) {
for (int j=0; j<MATRIX[0].length; j++) {
int rotatedMij = getCorrespondingElement90Cw(i,j);
if (rotatedMij >= MARKER) {
int originalRotatedElement = (rotatedMij - MARKER) / MAX_VALUE;
MATRIX[i][j] = MARKER + MATRIX[i][j] * MAX_VALUE + originalRotatedElement;
} else {
MATRIX[i][j] = MARKER + MATRIX[i][j] * MAX_VALUE + rotatedMij;
}
}
}

// cleanup to get only Mij_rotated
for (int i=0; i<MATRIX.length; i++) {
for (int j = 0; j < MATRIX[0].length; j++) {
MATRIX[i][j] = (MATRIX[i][j] - MARKER) % MAX_VALUE;
}
}

if (minValue < 0) {
addToOriginalMatrix(minValue); // restore original values in matrix
}

display();
}

public static void main(String args[]) {
new Exercise13().solveOnlyDisplay();
new Exercise13().solveWithSaving();
}
}