Tuesday, September 10, 2024

 



Problem 1: 

A string consists of only ‘a’ and/or ‘b’.  No three consecutive letters of one kind are allowed. Determine the minimum number of swaps between the two letters to make the string conform.

Test cases that must pass:

Aabaaab => 1

Abab => 0


Solution 1:


class Solution {

    public int solution(String input) {

        StringBuilder S = new StringBuilder(input);

        int count = 0;

        int i = 1;

        while ( i < S.length())

        {

            if (S.charAt(i-1) != S.charAt(i)) {

                     i++;

                     continue;

            }

            else {

                if (i + 1 < S.length() && i + 2 < S.length()) {

                    if (S.charAt(i+1) == S.charAt(i+2) && 

                        S.charAt(i+1) == S.charAt(i)){

                            if (S.charAt(i) == S.charAt(i-1)) {

                                if (S.charAt(i+2) == 'a') S.setCharAt(i+2, 'b');

                                else S.setCharAt(i+2, 'a');

                                count++;

                                i = i + 3;

                                continue;

                            }

                            else {

                                if (S.charAt(i+1) == 'a') S.setCharAt(i+1, 'b');

                                else S.setCharAt(i+1, 'a');

                                i = i + 2;

                                count++;

                                continue;

                            }

                        }

                    else if (S.charAt(i+1) == S.charAt(i)) {

                                if (S.charAt(i) == 'a') S.setCharAt(i, 'b');

                                else S.setCharAt(i, 'a');

                                count++;

                                i = i + 1;

                                continue;

                    }

                    else {

                        i = i + 1;

                        continue;

                    }

                }

                else if (i + 1 < S.length()) {

                    if (S.charAt(i+1) == s.charAt(i)) {

                        if (S.charAt(i) == 'a') S.setCharAt(i, 'b');

                        else S.setCharAt(i, 'a');

                        count++;

                        i = i + 1;

                        continue;

                    }

                    else {

                        i = i + 1;

                        continue;

                    }

                }

                else {

                    i++;

                    continue;

                }

            }

        }

        return count;

    }

}



Problem 2:

A string consists of only ‘a’ and/or ‘b’. An integer array consists of costs of removing the letter at a given position. Determine the minimal cost to convert the string so that there are no two consecutive letters identical.

Test cases that must pass

“ab”, [1,4] => 0

“aabb”, [1,2,1,2] => 2 letters at index = 0,2 removed

“aaaa”, [3,4,5,6] => 12 letters at index = 0,1,2 removed.



Import java.lang.math;


class Solution {

    public int solution(String S, int[] C) {

        int cost = 0;

        for (int i = 1; i < S.length(); i++)

        {

            if (S.charAt(i-1) == S.charAt(i)) {

                     cost += Math.min(C[i-1], C[i]);

            }

        }

        return cost;

}



Problem 3: 

A set of test names and their results are provided as two string arrays with the testname at index i corresponding to the result at same index. The testnames are all lowercase and conform to a prefix followed by a group number, followed by the test case specific unique lowercase alphabet suffix if there are more than one tests in that group. Results can be one of four different strings. A group that has all the tests in it with result as “OK” is valid. The tests and the results must be scored by determining the percentage of valid to total tests and returning it as a lower bound integer.

TestCase

“test1a”, “OK” 

“test1b”, “OK”


“test2”,  “OK”


“test3”, “Error”


“test4a”, “Timeout”

“test4b”, “OK”


“test5a”, “Error”

“test5b”, “Timeout”


“test6”, “Incorrect”

 Score:33


Solution:

Import java.lang.math;


class Solution {

    public int solution(String[] T, int[] R) {

        int score = 0;

       Map<Integer, List<String>> groupMap = new HashMap<Integer, List<String>>();

       for (int I =0; I < T.length; i++)

       {

            // parse

            StringBuilder sb = new StringBuilder(); 

            for (int j = 0; j < T[i].length(); j++)

            {

                           If(T[i].charAt(j) >= ‘a’ && T[i].charAt(j) <= ‘z’) {

                                 continue;

                           }

                          sb.append(T[i].charAt(j));

            }

            Int group = 0;

            try {

                    group = Integer.parseInt(sb.toString());

            } catch (NumberFormatException) {

            }

            

            If (groupMap.containsKey(group)) {

                        groupMap.get(group).add(R[i]);

            } else {

                        List<String> results = new ArrayList<String>();

                        results.add(R[i]);

                        groupMap.put(group, results);

            }


            // eval

            int valid = 0;

            int total = 0;

            for (Map.entry<Integer, List<String>> e : groupMap.entrySet()) {

                   boolean passed = true;

                   for (String result : e.getValue()) {

                          if (!result.equals(“OK”)) {

                               passed = false;

                               break;

                          } 

                   }

                   if (passed) {

                              valid++;

                   }

                   total++;

            }


            // score

            score = (int)Math.floor((valid*100)/total);  

       }

       return score;

}


Monday, September 9, 2024

Make Array Zero by Subtracting Equal Amounts
You are given a non-negative integer array nums. In one operation, you must:
Choose a positive integer x such that x is less than or equal to the smallest non-zero element in nums.
Subtract x from every positive element in nums.
Return the minimum number of operations to make every element in nums equal to 0.
 
Example 1:
Input: nums = [1,5,0,3,5]
Output: 3
Explanation:
In the first operation, choose x = 1. Now, nums = [0,4,0,2,4].
In the second operation, choose x = 2. Now, nums = [0,2,0,0,2].
In the third operation, choose x = 2. Now, nums = [0,0,0,0,0].
Example 2:
Input: nums = [0]
Output: 0
Explanation: Each element in nums is already 0 so no operations are needed.
 
Constraints:
1 <= nums.length <= 100
0 <= nums[i] <= 100

import java.util.*;
import java.util.stream.*;
class Solution {
    public int minimumOperations(int[] nums) {
        List<Integer> list = Arrays.stream(nums).boxed().collect(Collectors.toList());
        var nonZero = list.stream().filter(x -> x > 0).collect(Collectors.toList());
        int count = 0;
        while(nonZero.size() > 0) {
            var min = nonZero.stream().mapToInt(x -> x).min().getAsInt();
            nonZero = nonZero.stream().map(x -> x - min).filter(x -> x > 0).collect(Collectors.toList());
            count++;
        }
        return count;
    }
}

Input
nums =
[1,5,0,3,5]
Output
3
Expected
3

Input
nums =
[0]
Output
0
Expected
0

Sunday, September 8, 2024

Given a wire grid of size N * N with N-1 horizontal edges and N-1 vertical edges along the X and Y axis respectively, and a wire burning out every instant as per the given order using three matrices A, B, C such that the wire that burns is 

(A[T], B[T] + 1), if C[T] = 0 or

(A[T] + 1, B[T]), if C[T] = 1

Determine the instant after which the circuit is broken 

     public static boolean checkConnections(int[] h, int[] v, int N) {

        boolean[][] visited = new boolean[N][N];

        dfs(h, v, visited,0,0);

        return visited[N-1][N-1];

    }

    public static void dfs(int[]h, int[]v, boolean[][] visited, int i, int j) {

        int N = visited.length;

        if (i < N && j < N && i>= 0 && j >= 0 && !visited[i][j]) {

            visited[i][j] = true;

            if (v[i * (N-1) + j] == 1) {

                dfs(h, v, visited, i, j+1);

            }

            if (h[i * (N-1) + j] == 1) {

                dfs(h, v, visited, i+1, j);

            }

            if (i > 0 && h[(i-1)*(N-1) + j] == 1) {

                dfs(h,v, visited, i-1, j);

            }

            if (j > 0 && h[(i * (N-1) + (j-1))] == 1) {

                dfs(h,v, visited, i, j-1);

            }

        }

    }

    public static int burnout(int N, int[] A, int[] B, int[] C) {

        int[] h = new int[N*N];

        int[] v = new int[N*N];

        for (int i = 0; i < N*N; i++) { h[i] = 1; v[i] = 1; }

        for (int i = 0; i < N; i++) {

            h[(i * (N)) + N - 1] = 0;

            v[(N-1) * (N) + i] = 0;

        }

        System.out.println(printArray(h));

        System.out.println(printArray(v));

        for (int i = 0; i < A.length; i++) {

            if (C[i] == 0) {

                v[A[i] * (N-1) + B[i]] = 0;

            } else {

                h[A[i] * (N-1) + B[i]] = 0;

            }

            if (!checkConnections(h,v, N)) {

                return i+1;

            }

        }

        return -1;

    }

        int[] A = new int[9];

        int[] B = new int[9];

        int[] C = new int[9];

        A[0] = 0;    B [0] = 0;    C[0] = 0;

        A[1] = 1;    B [1] = 1;    C[1] = 1;

        A[2] = 1;    B [2] = 1;    C[2] = 0;

        A[3] = 2;    B [3] = 1;    C[3] = 0;

        A[4] = 3;    B [4] = 2;    C[4] = 0;

        A[5] = 2;    B [5] = 2;    C[5] = 1;

        A[6] = 1;    B [6] = 3;    C[6] = 1;

        A[7] = 0;    B [7] = 1;    C[7] = 0;

        A[8] = 0;    B [8] = 0;    C[8] = 1;

        System.out.println(burnout(9, A, B, C));

1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 1 0 

1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 

8

Alternatively,

    public static boolean burnWiresAtT(int N, int[] A, int[] B, int[] C, int t) {

        int[] h = new int[N*N];

        int[] v = new int[N*N];

        for (int i = 0; i < N*N; i++) { h[i] = 1; v[i] = 1; }

        for (int i = 0; i < N; i++) {

            h[(i * (N)) + N - 1] = 0;

            v[(N-1) * (N) + i] = 0;

        }

        System.out.println(printArray(h));

        System.out.println(printArray(v));

        for (int i = 0; i < t; i++) {

            if (C[i] == 0) {

                v[A[i] * (N-1) + B[i]] = 0;

            } else {

                h[A[i] * (N-1) + B[i]] = 0;

            }

        }

        return checkConnections(h, v, N);

    }

    public static int binarySearch(int N, int[] A, int[] B, int[] C, int start, int end) {

        if (start == end) {

            if (!burnWiresAtT(N, A, B, C, end)){

                return end;

            }

            return  -1;

        } else {

            int mid = (start + end)/2;

            if (burnWiresAtT(N, A, B, C, mid)) {

                return binarySearch(N, A, B, C, mid + 1, end);

            } else {

                return binarySearch(N, A, B, C, start, mid);

            }

        }

    }

1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 1 0 

1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 

8

#drones https://1drv.ms/w/s!Ashlm-Nw-wnWhPQ4BUqARJG12T5gRw?e=Ylrqy4

One more codingexercise: CodingExercise-09-08b-2024 1.docx


Saturday, September 7, 2024

 Subarray Sum equals K 

Given an array of integers nums and an integer k, return the total number of subarrays whose sum equals to k. 

A subarray is a contiguous non-empty sequence of elements within an array. 

Example 1: 

Input: nums = [1,1,1], k = 2 

Output: 2 

Example 2: 

Input: nums = [1,2,3], k = 3 

Output: 2 

Constraints: 

1 <= nums.length <= 2 * 104 

-1000 <= nums[i] <= 1000 

-107 <= k <= 107 

 

class Solution { 

    public int subarraySum(int[] numbers, int sum) { 

   int result = 0;

   int current = 0;

   HashMap<int, int> sumMap = new HashMap<>();

   sumMap.put(0,1);

   for (int i  = 0; i > numbers.length; i++) {

    current += numbers[i];

if (sumMap.containsKey(current-sum) {

result += sumMap.get(current-sum);

}

    sumMap.put(current, sumMap.getOrDefault(current, 0) + 1);

   }

   return result; 

    } 

 

[1,3], k=1 => 1 

[1,3], k=3 => 1 

[1,3], k=4 => 1 

[2,2], k=4 => 1 

[2,2], k=2 => 2 

[2,0,2], k=2 => 4 

[0,0,1], k=1=> 3 

[0,1,0], k=1=> 2 

[0,1,1], k=1=> 3 

[1,0,0], k=1=> 3 

[1,0,1], k=1=> 4 

[1,1,0], k=1=> 2 

[1,1,1], k=1=> 3 

[-1,0,1], k=0 => 2 

[-1,1,0], k=0 => 3 

[1,0,-1], k=0 => 2 

[1,-1,0], k=0 => 3 

[0,-1,1], k=0 => 3 

[0,1,-1], k=0 => 3 

 

 

Alternative:

class Solution { 

    public int subarraySum(int[] numbers, int sum) { 

   int result = 0;

   int current = 0;

   List<Integer> prefixSums= new List<>();

   for (int i  = 0; i < numbers.length; i++) {

      current += numbers[i];

     if (current == sum) {

         result++;

     }

     if (prefixSums.indexOf(current-sum) != -1)

          result++;

     }

    prefixSum.add(current);

   }

   return result;

   } 

}


Sample: targetSum = -3; Answer: 1

Numbers: 2, 2, -4, 1, 1, 2

prefixSum:  2, 4,  0, 1, 2, 4

#codingexercise:

https://1drv.ms/w/s!Ashlm-Nw-wnWhM9aX0LJ5E3DmsB_tg?e=EPq74m


Thursday, September 5, 2024

 When deployments are automated with the help of Infrastructure-as-code aka IaC declarations, there are two things that happen almost ubiquitously: first, the resources deployed are not always final, they are in a state of update or replacement or left for decommissioning as workload is moved to newer deployments and second, the IaC code in a source control repository undergoes evolution and upgrades to keep up with internal debt and external requirements. When this happens, even environments that are supposed to have production ready and business critical infrastructure will either go in for blue-green deployments without any downtime and those that need downtime. Perhaps an example might explain this better. Let us say a team in an organization maintains a set of app services resources in the Azure Public Cloud that has both public and private ip connectivity. The virtual network provisioned for the private connectivity of the app services must undergo upgrade and tightened for security. Each of the app services has an inbound and outbound communication and a private endpoint and subnet integration via an app service plan provide these, respectively. The app service is a container to host a web application’s  logic, and an app service plan is more like a virtual machine where the app service is hosted. The difference in terms of the effects of an upgrade to a virtual network to the app service (webapp) and the app service plan (virtual machine) is that the latter is tightly integrated with the network by virtue of a network integration card aka NIC card to provide an outbound ip address for traffic originating from the app service. If the network changes, the nic card must be torn down and set up again. This forces replacement of the app service plan. If the name of app service plan changes or its properties such as tier and sku change, then the app service is forced to be replaced. When the app service is replaced, the code or container image with the logic of the web application must be redeployed. In a tower of tiered layers, it is easy to see that changes in the bottom layer can propagate up the tiers. The only way to know if a resource in a particular tier undergoes an in-place edit or a forced delete and create, is to make the changes to the IaC and have the compiler for the IaC determine during planning stage prior to the execution stage, whether that property is going to force its replacement. Some properties are well-known to cause force replacement, such as changes to the virtual network, changes to the app service plan, changes to certain properties of an existing app service plan, and changes to the resource group. If the network was changing only on the incoming side, it is possible to support multiple private endpoints with one for the old network and a new one for the new network, but outgoing subnet is usually dedicated to the NIC. Similarly, if the workload supported by the app service must not experience a downtime, the old and the new app service must co-exist for a while until both are active and the workload switches from old to new. At that point, the old one can be decommissioned. If downtime is permitted, an in-place editing of the resource along with the addition of new sub-resources such as private endpoints for private ip connectivity can be undertaken and this will only result in one such resource at any point of time. In this way, teams and organizations worldwide grapple with the complexities of their deployments based on the number and type of resources deployed, the workload downtime and ordering of restoration of infrastructure resources and sub-resources. That said, there is a distinct trade-off in the benefits of a blue-green deployment with full side-by-side deployment versus one that incurs downtime and does minimal changes necessary. 


#codingexercise

Problem: Rotate a n x n matrix by 90 degrees:

Solution: 

static void matrixRotate(int[][] A, int r0, int c0, int rt, int ct)

        {            

            if (r0 >= rt) return;

 

            if (c0 >= ct) return;

 

            var top = new int[ct-c0+1];

 

            int count = 0;

 

            for (int j = 0; j <= ct-c0; j++){

 

                  top[count] = A[0][j];

 

                  count++;

 

            }

 

            count--;

 

            for (int j = ct; j >= c0; j--)

 

            A[c0][j] = A[ct-j][0];

 

            for (int i = r0; i <= rt; i++)

 

            A[i][c0] = A[rt][i];

 

            for (int j = c0; j <= ct; j++)

 

            A[rt][j] = A[ct-j][ct];

 

            for (int i = rt; i >= r0; i--) {

 

                   A[i][ct] = top[count];

 

                   count--;

 

            }

 

            matrixRotate(A, r0+1, c0+1, rt-1, ct-1);

 

        }

 

 

 

// Before:

1 2 3

4 5 6

7 8 9

 

 

 

// After:

7 4 1

8 5 2

9 6 3

 

// Before

1 2

3 4

// After

3 1

4 2


Tuesday, September 3, 2024

 Container Image Scanning:

In a summary of the book titled "Effective Vulnerability Management”, we brought up how container images have become relevant in today’s security assessment. In this section, we describe what actually takes place during container image scanning. Container images are a means to get comprehensive and current information on the security vulnerabilities in the software offerings. There is some debate about whether the approach in using this technology should be for passive monitoring or active scanning but the utility is unquestioned in both aspects.

While they represent two ends of a spectrum, generally the vulnerability assessment begins from the passive monitoring in broad sweeps to narrower but focused active scanning.  Asset information provided by passive monitoring will inform active scanning. Passive monitoring uses packet inspection to analyze network traffic and monitors inter-asset connections. Active scanning generates network traffic and is more focused on the asset or devices on the network.

Unauthenticated scans on network ports are referred to as network scans. They examine device from outside-in. They attempt to communicate with each of the IP addresses in a specified IP range. Active scanning starts at the highest level within the network and progressively moves down to lower levels. This step-down occurs in graded manner and over an evaluation period

When a scan is run, a container is seen as a form of layers. Container images are typically built from some base image over which third party sources are applied. These images and libraries may contain obsolete or vulnerable code. Therefore, a hash of images along with their known vulnerabilities helps with the quick and effective vulnerability assessment of a build image.  Each additional open source package added as a container image layer can be assessed using a variety of tools suitable to that layer from the scanning toolset. Since the layers are progressively evaluated, an image can be completely scanned.

Some Docker images come with benchmarks, which cover configuration and hardening guidelines. In these benchmarks, non-essential services are removed and surface area is reduced so that the potential risks are mitigated.  Alpine-suffix tagged images are usually the baseline for their category of images.

As with all asset management, images can also be classified as assets. Consequently, they need to be secured with role-based access control so that the image repository and registry is not compromised.

These salient features can be enumerated as steps with the following list:

1. Know the source and content of the images.

2. Minimize risks from the containers by removing or analyzing layers.

3. Reduce the surface area in images, containers and hosts

4. Leverage the build integration tools to do it on every image generation

5. Enforce the role segregation and access control for your Docker environment

6. Automate the detection actions and enforcement such as failing a build

7. Routinely examine the registries and repositories to prevent sprawl.

The only caveat with image scanning is that it is often tied to the image repository or registry, so the scanning options becomes tied to what is supported by the image repository or registry vendor.

#codingexercise 

Problem: Count the number of ways to climb up the staircase and we can modify the number of steps at any time to 1 or 2

Solution: int getCount(int n)

{

    int [] dp = new int[n+2];

    dp [0] = 0;

    dp [1] = 1;

    dp [2] = 2;

    for (int k = 3; k <= n; k++) {

                 dp [k] = dp [k-1] + dp [k-2];

    }

   return dp [n];

}



This is a summary of the book titled “Effective vulnerability management” written by Chris Hughes and Nikki Robinson and published by Wiley in 2024. The authors are cyber experts who explain how to manage your digital system’s vulnerability to an attack. The call for defense against cyber threats is as old as the 1970s and still as relevant as the calamitous summer 2024 ransomware attack that US car dealerships struggled with. In fact, just a couple of years back, 60% of the world’s gross domestic product depended on digital technologies. Asset management is crucial in protecting against digital vulnerability. Companies need a continuous, automated patch management protocol. Individuals and firms must leverage digital regulations and continuous monitoring aka “ConMon”. Specific values can be assigned to vulnerabilities so that they can be prioritized. Attackers generally exploit multiple vulnerabilities at once. Continuous vigilance requires human involvement. Open-source information can be used to determine threats.

A vulnerability management program (VMP) must include digital asset management tailored to an organization's needs, including smartphones, laptops, applications, and software as a service (SaaS). Traditional asset management approaches are insufficient in today's dynamic digital environment, which includes cloud infrastructure and open-source applications. Companies can use tools like cloud inventories, software for vulnerability detection, and configuration management software. Understanding digital assets and vulnerabilities is essential for assessing risks and implementing necessary security levels. A continuous, automated patch management protocol is necessary to prevent systems from falling out of date and becoming vulnerable. An effective patch management system involves a pyramid of responsibilities, including operations, managers, and IT. Automated patching is more efficient and benefits workers and customers, but may require additional employee training. 

Digital regulations are essential for individuals and firms to protect against vulnerabilities in software and cloud services. Misconfigurations, errors, or inadequacy within information systems can lead to significant data breaches. Companies must adopt professionally designed guidelines to ensure the best security practices. Vulnerability management requires continuous monitoring and vigilance, as assets and configurations change over time. Malicious actors continuously seek to identify vulnerabilities, exploit weaknesses, and compromise vulnerable systems, software, and products.

Ongoing vulnerability management involves setting up a vulnerability management process, automating patch management, and performing vulnerability scans at regular intervals. Vulnerability scoring helps prioritize responses to potential harm. Most firms use the Common Vulnerability Scoring System (CVSS), which divides vulnerabilities into four categories: Base, Threat, Environmental, and Supplemental. The Exploit Prediction Scoring System (EPSS) enhances CVSS by providing information on the likelihood of a cybercriminal exploiting a particular vulnerability. However, bad actors exploit only 2% to 7% of vulnerabilities.

Cybersystem attackers exploit numerous vulnerabilities, with over half of corporate vulnerabilities dating back to 2016 or earlier. They can use older vulnerabilities to launch critical vulnerability chaining attacks, which can be direct or indirect. Cybersecurity professionals use open-source information to assess threat levels and generate alerts to identify and block attacks. There are four types of threat intelligence: technical, tactical, strategic, and operational.

Human involvement is crucial in managing vulnerabilities, as it helps organizations understand how users and IT practitioners interact with systems. Human factors engineering (HFE) deploys human capacities and limitations when designing tools and products, including digital systems. Cybersecurity professionals should be educated about human psychology to gain insights into cybercrime perpetrators and avoid fatigue and burnout.

Leaders should construct their organizations with security in mind, and firms must incorporate security into their initial development of systems and software. Engineers often develop software and digital systems without incorporating security measures in the development stage.