Wednesday, September 25, 2024

 Manifesting Dependencies:

Among the frequently encountered disconcerting challenges faced by engineers who deploy infrastructure is the way to understand, capture and use dependencies. Imagine a clone army where all entities look alike and a specific one or two need to be replaced. Without having a name or identifier at hand, it is difficult to locate those entities but it becomes even harder when we don’t know which of the others are actually using them, so that we are mindful of the consequences of replacements. Grounding this example with cloud resources in azure public cloud, we can take a set of resources with a private endpoint each that gives them a unique private IP address, and we want to replace the virtual network that is integrated with these resources. When we switch the virtual network, the old and the new do not interact with one another and traffic that was flowing to a resource on the old network is now disrupted when that resource moves to a different virtual network. Unless we have all the dependencies known about who is using the resource that is about to move, we cannot resolve the failures they might encounter. What adds to the challenge is that the virtual network is like a carpet on which the resources stand and this resource type is always local to an availability zone or region so there is no built-in redundancy or replica available to ease the migration. One cannot just move the resource as if it were moving from one resource group to another, it must be untethered and tied to another virtual network with a delete of the old private endpoint and the addition of a new. Taking the example a little further, IaC does not capture dependencies between usages of resources. It only captures dependencies on creation or modification. For example, a workspace that users access to spin up compute and run their notebooks. might be using a container registry over the virtual network but its dependency does not get manifested because the registry does not maintain a list of addresses or networks to allow. The only way to reverse-engineer the listing of dependencies is to check the dns zone records associated with the private endpoint and the entries added to the callers that resolve the container registry over the virtual network. These entries will have private IP addresses associated with the callers and by virtue of the address belong to an address space designated to a sub-network, it is possible to tell whether it came from a connection device associated with a compute belonging to the workspace. By painful enumeration of each of these links, it is possible to draw a list of all workspaces using the container registry. These records that helped us draw the list may have a lot of stale entries as the callers disappear but do not clean up the record. So, some pruning might be involved and it might change over time but it will still be handy.



Tuesday, September 24, 2024

 

Problem: Given a weighted bidirectional graph with N nodes and M edges and all the weights as distinct positive numbers, find the maximum number of edges that can be visited on traversing the graph such that the weights are ascending.

Solution: When a weighted edge is encountered in an ascending order between nodes, say u and v, it must be the first edge of the path starting at either u or v and no other nodes. In addition, that path starts at one vertex, goes through edge uv and then the remaining longest ascending path up to the other vertex. Therefore, the weights accumulated at both these nodes is the maximum of (w[u], w[v] + 1) and (w[v], w[u]+1) in an array w of weights of longest ascending paths starting at that vertex.

 

public static int solution_unique_weights(int N, int[] src, int[] dest, int[] weight) {

            int M = weight.length;

            int[] e = new int[N];

            Integer[] index = new Integer[M];

            for (int i = 0; i <M; i++) { index[i] = i; }

            Comparator<Integer> comparator = (i, j) -> weight[j] - weight[i];

            Arrays.sort(index, 0, M, comparator);

            for (int I = 0; i< M; i++) {

                          int u = src[index[i]];

                          int v = dest[index[i]];

                           int count = Math.max(Math.max(e[u], e[v] + 1), Math.max(e[v], e[u]+1));

                           e[u] = count;

                           e[v] = count;

             }

             return Arrays.stream(e).max().getAsInt();

    }

 

    src[0] = 0    dest[0] = 1    weight[0] = 4

    src[1] = 1    dest[1] = 2    weight[1] = 3

    src[2] = 1    dest[2] = 3    weight[2] = 2

    src[3] = 2    dest[3] = 3    weight[3] = 5

    src[4] = 3    dest[4] = 4    weight[4] = 6

    src[5] = 4    dest[5] = 5    weight[5] = 7

    src[6] = 5    dest[6] = 0    weight[6] = 9

    src[7] = 3    dest[7] = 2    weight[7] = 8

    index:  0 1 2 3 4 5 6 7  // before sort

    index:  2 1 0 3 4 5 7 6  // after sort

    e: 

    0  1  0  1  0  0  0  0

    0  2  2  1  0  0  0  0

    3  3  2  1  0  0  0  0

    3  3  3  4  4  0  0  0

    3  3  3  4  5  5  0  0

    3  3  4  4  5  5  0  0

    6  3  4  4  5  6  0  0

    

With the longest ascending path being nodes 3->1->2->3->4->5->0 and 6 edges

 

Monday, September 23, 2024

 Infrastructure as a top-down approach versus bottom-up growth.

Centralized planning has many benefits for infrastructure as evidenced by parallels in construction industry and public transportation. The top-down approach in this context typically refers to a method where policy decisions and strategies are formulated at a higher, often governmental or organizational level, and then implemented down through various levels of the system. This approach contrasts with a bottom-up approach, where policies and strategies are developed based on input and feedback from lower levels, such as local communities or individual stakeholders.

Such a regulatory approach might involve:

Centralized Planning: High-level authorities set infrastructure policies and plans, which are then executed by regional or local agencies.

Regulation and Standards: Establishing uniform regulations and standards for cloud systems, which must be adhered to by all stakeholders.

Funding Allocation: Decisions on the allocation of funds for infrastructure projects are made at a higher level, often based on broader economic and policy goals.

This approach can ensure consistency and alignment with national or regional objectives, but it may also face challenges such as lack of local adaptability and slower response to specific local needs.

On the other hand, a bottom-up approach typically involves building and configuring resources starting from the lower levels of the infrastructure stack, often driven by the needs and inputs of individual teams or developers. This approach contrasts with a top-down approach, where decisions and designs are made at a higher organizational level and then implemented downwards.

Here are some key aspects of the bottom-up approach in Azure deployments:

Developer-Driven: Individual developers or teams have the autonomy to create and manage their own resources, such as virtual machines, databases, and networking components, based on their specific project requirements.

Incremental Development: Infrastructure is built incrementally, starting with basic components and gradually adding more complex services and configurations as needed. This allows for flexibility and adaptability.

Agility and Innovation: Teams can experiment with new services and technologies without waiting for centralized approval, fostering innovation and rapid iteration.

Infrastructure as Code (IaC): Tools like Terraform and Azure Resource Manager (ARM) templates are often used to define and manage infrastructure programmatically. This allows for version control, repeatability, and collaboration.

Feedback Loops: Continuous feedback from the deployment and operation of resources helps teams to quickly identify and address issues, optimizing the infrastructure over time.

This approach can be particularly effective in dynamic environments where requirements change frequently, and rapid deployment and scaling are essential

The right approach depends on a blend of what suits the workloads demanded by the business in the most expedient manner with iterative improvements and what can be curated as patterns and best practices towards a system architecture that will best serve the organization in the long run across changes in business requirements and directions.


Sunday, September 22, 2024

 This is a summary of the book titled “Cash is King” written by Peter W. Kingma and published by Wiley in 2024. As an entrepreneur, founders usually chase revenue, and cash is secondary concern but firms with strong cash positions can seize new opportunities and remain flexible. Using a fictional Owens Inc. the author draws this point through a comprehensive treatise on the topic of cash management. The procurement process from order placement to payment affects a company’s cash position. Business functions such as marketing and warehousing can also help optimize the cash position. Logistics, which is usually dynamic in nature, can help with inventory management and reduce cash freezes. The cash position for a firm can benefit from working capital management. Performance measurement metrics can aid managers. Improved cash management can boost a business’ resilience and guide it through bad times.

A business should prioritize cash flow over revenue generation to sustain growth. For example, Owens Inc., a manufacturer of electrical equipment, found that its sales terms were too favorable, and its internal processes were complicated, affecting invoicing and collections. The company's growth was driven by risk-taking and sales growth, but it neglected inventory management and internal processes. To manage sales and client management, companies should segment customers, implement credit review policies, track invoice payments, set collector targets, and adopt electronic payment methods. The procurement process, from order placement to payment, also impacts on a company's cash position. The procurement team must manage routine processes and deal with emergencies daily. The procurement team faces pressure and may not notice trade-offs that affect a company's cash position, such as lead times, minimum order quantities, and delivery times.

Business functions like marketing and warehousing can optimize cash position by synchronizing their interests and goals. Procurement personnel should focus on negotiating the best prices, while logistics management should be dynamic and adaptable to changing customer needs, transportation costs, and innovation. Marketing and engineering functions should monitor inventory to identify lost demand and ensure legitimate demand for new products. Logistics and warehousing should aim for higher service levels, requiring more inventory.

Logistics can affect a firm's cash flow through variations in batch size, use of technology, standardized terms of trade, customer-negotiated service terms, optimal warehouse management, and linking customer status updates to billing functions. These factors can disrupt existing dynamics and impact inventory management. The COVID-19 pandemic and global supply chains have also impacted inventory management.

Plant management procedures can optimize inventory investment for optimal returns. Investing in inventory that sells quickly and at a high margin yields more favorable returns than unused inventory. Safety stock is the level of inventory required to meet customer service standards, calculated based on historical variations. Minimal stock on hand for made-to-order products and minimal stock in transit can help reduce transportation time and minimum order requirements. Working capital management can improve a firm's cash position. A good financial controller can help businesses tackle accounting and financial reporting, following best practices like absorption costing and weighted average cost of capital (WACC). A company's stock price is affected by debt, and controllers should be cautious of using short-term debt costs without considering equity costs. Strong performance in one area can mask poor performance in another.

Managers should effectively use performance measurement metrics to gauge business performance and make informed decisions. Common metrics include inventory turns and cost per unit. However, they often do not align with operational metrics, leading to data integration issues or lack of review. Leadership metrics should serve as warning lights, guiding the company's health before it is too late. Operating metrics should capture the input management needs to measure, and key performance indicators and bonuses should be aligned with cash performance.

Improved cash management can boost a business's resilience and guide it through bad times. Recognizing the importance of cash flow is crucial, but many businesses consider it an afterthought. Companies with above-average working capital management tend to bounce back faster from setbacks and preserve shareholder capital better. Cash management is equally important for service sector firms, but the considerations are different.

To bring about sustainable changes, a cash leadership office should be formed, focusing on both cash position and growth. This ensures that the entire management team is on the same page and can advise the business on trade-offs or compromises.


Saturday, September 21, 2024

 Given clock hands positions for different points of time as pairs A[I][0] and A[I][1] where the order of the hands does not matter but their angle enclosed, count the number of pairs of points of time where the angles are the same

    public static int[] getClockHandsDelta(int[][] A) {

        int[] angles = new int[A.length];

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

            angles[i] = Math.max(A[i][0], A[i][1]) - Math.min(A[i][0],A[i][1]);

        }

        return angles;

    }

    public static int NChooseK(int n, int k)

    {

        if (k < 0 || k > n || n == 0) return 0;

        if ( k == 0 || k == n) return 1;

        return Factorial(n) / (Factorial(n-k) * Factorial(k));

    }

 

    public static int Factorial(int n) {

        if (n <= 1) return 1;

        return n * Factorial(n-1);

    }


    public static int countPairsWithIdenticalAnglesDelta(int[] angles){

        Arrays.sort(angles);

        int count = 1;

        int result = 0;

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

            if (angles[i] == angles[i-1]) {

                count += 1;

            } else {

                if (count > 0) {

                    result += NChooseK(count, 2);

                }

                count = 1;

            }

        }

        if (count > 0) {

            result += NChooseK(count, 2);

            count = 0;

        }

        return result;

    }


        int [][] A = new int[5][2];

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

         A[1][0] = 2;    A[1][1] = 4;

         A[2][0] = 4;    A[2][1] = 3;

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

         A[4][0] = 1;    A[4][1] = 3;

 1 2 1 1 2 

1 1 1 2 2 

4


Friday, September 20, 2024

 Decode ways:

A message containing letters from A-Z can be encoded into numbers using the following mapping:

'A' -> "1"

'B' -> "2"

...

'Z' -> "26"

To decode an encoded message, all the digits must be grouped then mapped back into letters using the reverse of the mapping above (there may be multiple ways). For example, "11106" can be mapped into:

"AAJF" with the grouping (1 1 10 6)

"KJF" with the grouping (11 10 6)

Note that the grouping (1 11 06) is invalid because "06" cannot be mapped into 'F' since "6" is different from "06".

Given a string s containing only digits, return the number of ways to decode it.

The test cases are generated so that the answer fits in a 32-bit integer.

 

Example 1:

Input: s = "12"

Output: 2

Explanation: "12" could be decoded as "AB" (1 2) or "L" (12).

Example 2:

Input: s = "226"

Output: 3

Explanation: "226" could be decoded as "BZ" (2 26), "VF" (22 6), or "BBF" (2 2 6).

Example 3:

Input: s = "06"

Output: 0

Explanation: "06" cannot be mapped to "F" because of the leading zero ("6" is different from "06").

 

Constraints:

1 <= s.length <= 100

s contains only digits and may contain leading zero(s).


class Solution {

    public int numDecodings(String s) {

        Integer count = 0;

        if (isValid(s.substring(0,1))) 

            traverse(s.substring(1), count);

        if (s.length() >= 2 && isValid(s.substring(0,2))) 

            traverse(s.substring(2), count);

        return count;

    }

    public boolean traverse(String s, Integer count) {

        if (String.isNullOrWhitespace(s)){

            count += 1;

            return true;

        }

        if (isValid(s.substring(0,1)))

            traverse(s.substring(1), count);

        if (s.length() >= 2 && isValid(s.substring(0,2)))

            traverse(s.substring(2), count);

        return count > 0;

    }

    public boolean isValid(String s) {

        if (s.length() == 1 && s.charAt(0) >= '0' && s.charAt(0) <= '9'){

            return true;

        }

        if (s.length() == 2 && 

           (s.charAt(0) > '0' && s.charAt(0) <= '2') && 

           ((s.charAt(0) == '1' && s.charAt(1) >= '0' && s.chartAt(1) <= '9') || 

            (s.charAt(0) == '2' && s.chartAt(1) >= '0' && s.chartAt(1) <= '6')) {

            return true;

        }

        return false;

    }

}


Thursday, September 19, 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